home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / clang / cweb31.zip / CWEAVE.W (.txt) < prev    next >
Texinfo Document  |  1993-11-08  |  161KB  |  3,596 lines

  1. % This file is part of CWEB.
  2. % This program by Silvio Levy and Donald E. Knuth
  3. % is based on a program by Knuth.
  4. % It is distributed WITHOUT ANY WARRANTY, express or implied.
  5. % Version 3.1 --- November 1993
  6. % Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth
  7. % Permission is granted to make and distribute verbatim copies of this
  8. % document provided that the copyright notice and this permission notice
  9. % are preserved on all copies.
  10. % Permission is granted to copy and distribute modified versions of this
  11. % document under the conditions for verbatim copying, provided that the
  12. % entire resulting derived work is distributed under the terms of a
  13. % permission notice identical to this one.
  14. % Here is TeX material that gets inserted after \input cwebmac
  15. \def\hang{\hangindent 3em\indent\ignorespaces}
  16. \def\pb{$\.|\ldots\.|$} % C brackets (|...|)
  17. \def\v{\char'174} % vertical (|) in typewriter font
  18. \def\dleft{[\![} \def\dright{]\!]} % double brackets
  19. \mathchardef\RA="3221 % right arrow
  20. \mathchardef\BA="3224 % double arrow
  21. \def\({} % ) kludge for alphabetizing certain section names
  22. \def\TeXxstring{\\{\TEX/\_string}}
  23. \def\skipxTeX{\\{skip\_\TEX/}}
  24. \def\copyxTeX{\\{copy\_\TEX/}}
  25. \def\title{CWEAVE (Version 3.1)}
  26. \def\topofcontents{\null\vfill
  27.   \centerline{\titlefont The {\ttitlefont CWEAVE} processor}
  28.   \vskip 15pt
  29.   \centerline{(Version 3.1)}
  30.   \vfill}
  31. \def\botofcontents{\vfill
  32. \noindent
  33. Copyright \copyright\ 1987, 1990, 1993 Silvio Levy and Donald E. Knuth
  34. \bigskip\noindent
  35. Permission is granted to make and distribute verbatim copies of this
  36. document provided that the copyright notice and this permission notice
  37. are preserved on all copies.
  38. \smallskip\noindent
  39. Permission is granted to copy and distribute modified versions of this
  40. document under the conditions for verbatim copying, provided that the
  41. entire resulting derived work is distributed under the terms of a
  42. permission notice identical to this one.
  43. \pageno=\contentspagenumber \advance\pageno by 1
  44. \let\maybe=\iftrue
  45. @** Introduction.
  46. This is the \.{CWEAVE} program by Silvio Levy and Donald E. Knuth,
  47. based on \.{WEAVE} by Knuth.
  48. We are thankful to Steve Avery,
  49. Nelson Beebe, Hans-Hermann Bode (to whom the \CPLUSPLUS/ adaptation is due),
  50. Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,
  51. Joachim Schrod, Lee Wittenberg, and others who have contributed improvements.
  52. The ``banner line'' defined here should be changed whenever \.{CWEAVE}
  53. is modified.
  54. @d banner "This is CWEAVE (Version 3.1)\n"
  55. @c @<Include files@>@/
  56. @<Common code for \.{CWEAVE} and \.{CTANGLE}@>@/
  57. @<Typedef declarations@>@/
  58. @<Global variables@>@/
  59. @<Predeclaration of procedures@>
  60. @ We predeclare several standard system functions here instead of including
  61. their system header files, because the names of the header files are not as
  62. standard as the names of the functions. (For example, some \CEE/ environments
  63. have \.{<string.h>} where others have \.{<strings.h>}.)
  64. @<Predecl...@>=
  65. extern int strlen(); /* length of string */
  66. extern int strcmp(); /* compare strings lexicographically */
  67. extern char* strcpy(); /* copy one string to another */
  68. extern int strncmp(); /* compare up to $n$ string characters */
  69. extern char* strncpy(); /* copy up to $n$ string characters */
  70. @ \.{CWEAVE} has a fairly straightforward outline.  It operates in
  71. three phases: First it inputs the source file and stores cross-reference
  72. data, then it inputs the source once again and produces the \TEX/ output
  73. file, finally it sorts and outputs the index.
  74. Please read the documentation for \.{common}, the set of routines common
  75. to \.{CTANGLE} and \.{CWEAVE}, before proceeding further.
  76. int main (ac, av)
  77. int ac; /* argument count */
  78. char **av; /* argument values */
  79.   argc=ac; argv=av;
  80.   program=cweave;
  81.   make_xrefs=force_lines=1; /* controlled by command-line options */
  82.   common_init();
  83.   @<Set initial values@>;
  84.   if (show_banner) printf(banner); /* print a ``banner line'' */
  85.   @<Store all the reserved words@>;
  86.   phase_one(); /* read all the user's text and store the cross-references */
  87.   phase_two(); /* read all the text again and translate it to \TEX/ form */
  88.   phase_three(); /* output the cross-reference index */
  89.   return wrap_up(); /* and exit gracefully */
  90. @ The following parameters were sufficient in the original \.{WEAVE} to
  91. handle \TEX/, so they should be sufficient for most applications of \.{CWEAVE}.
  92. If you change |max_bytes|, |max_names|, |hash_size| or |buf_size|
  93. you have to change them also in the file |"common.w"|.
  94. @d max_bytes 90000 /* the number of bytes in identifiers,
  95.   index entries, and section names */
  96. @d max_names 4000 /* number of identifiers, strings, section names;
  97.   must be less than 10240; used in |"common.w"| */
  98. @d max_sections 2000 /* greater than the total number of sections */
  99. @d hash_size 353 /* should be prime */
  100. @d buf_size 100 /* maximum length of input line, plus one */
  101. @d longest_name 1000 /* section names and strings shouldn't be longer than this */
  102. @d long_buf_size (buf_size+longest_name)
  103. @d line_length 80 /* lines of \TEX/ output have at most this many characters;
  104.   should be less than 256 */
  105. @d max_refs 20000 /* number of cross-references; must be less than 65536 */
  106. @d max_toks 20000 /* number of symbols in \CEE/ texts being parsed;
  107.   must be less than 65536 */
  108. @d max_texts 4000 /* number of phrases in \CEE/ texts being parsed;
  109.   must be less than 10240 */
  110. @d max_scraps 2000 /* number of tokens in \CEE/ texts being parsed */
  111. @d stack_size 400 /* number of simultaneous output levels */
  112. @ The next few sections contain stuff from the file |"common.w"| that must
  113. be included in both |"ctangle.w"| and |"cweave.w"|. It appears in
  114. file |"common.h"|, which needs to be updated when |"common.w"| changes.
  115. @i common.h
  116. @* Data structures exclusive to {\tt CWEAVE}.
  117. As explained in \.{common.w}, the field of a |name_info| structure
  118. that contains the |rlink| of a section name is used for a completely
  119. different purpose in the case of identifiers.  It is then called the
  120. |ilk| of the identifier, and it is used to
  121. distinguish between various types of identifiers, as follows:
  122. \yskip\hang |normal| identifiers are part of the \CEE/ program and
  123. will appear in italic type.
  124. \yskip\hang |roman| identifiers are index entries that appear after
  125. \.{@@\^} in the \.{CWEB} file.
  126. \yskip\hang |wildcard| identifiers are index entries that appear after
  127. \.{@@:} in the \.{CWEB} file.
  128. \yskip\hang |typewriter| identifiers are index entries that appear after
  129. \.{@@.} in the \.{CWEB} file.
  130. \yskip\hang |else_like|, \dots, |typedef_like|
  131. identifiers are \CEE/ reserved words whose |ilk| explains how they are
  132. to be treated when \CEE/ code is being formatted.
  133. @d ilk dummy.Ilk
  134. @d normal 0 /* ordinary identifiers have |normal| ilk */
  135. @d roman 1 /* normal index entries have |roman| ilk */
  136. @d wildcard 2 /* user-formatted index entries have |wildcard| ilk */
  137. @d typewriter 3 /* `typewriter type' entries have |typewriter| ilk */
  138. @d abnormal(a) (a->ilk>typewriter) /* tells if a name is special */
  139. @d custom 4 /* identifiers with user-given control sequence */
  140. @d unindexed(a) (a->ilk>custom) /* tells if uses of a name are to be indexed */
  141. @d quoted 5 /* \.{NULL} */
  142. @d else_like 26 /* \&{else} */
  143. @d public_like 40 /* \&{public}, \&{private}, \&{protected} */
  144. @d operator_like 41 /* \&{operator} */
  145. @d new_like 42 /* \&{new} */
  146. @d catch_like 43 /* \&{catch} */
  147. @d for_like 45 /* \.{for}, \&{switch}, \&{while} */
  148. @d do_like 46 /* \&{do} */
  149. @d if_like 47 /* \&{if}, \&{ifdef}, \&{endif}, \&{pragma}, \dots */
  150. @d raw_rpar 48 /* `\.)' or `\.]' when looking for \&{const} following */
  151. @d raw_unorbin 49 /* `\.\&' or `\.*' when looking for \&{const} following */
  152. @d const_like 50 /* \&{const}, \&{volatile} */
  153. @d raw_int 51 /* \&{int}, \&{char}, \&{extern}, \dots  */
  154. @d int_like 52 /* same, when not followed by left parenthesis */
  155. @d case_like 53 /* \&{case}, \&{return}, \&{goto}, \&{break}, \&{continue} */
  156. @d sizeof_like 54 /* \&{sizeof} */
  157. @d struct_like 55 /* \&{struct}, \&{union}, \&{enum}, \&{class} */
  158. @d typedef_like 56 /* \&{typedef} */
  159. @d define_like 57 /* \&{define} */
  160. @ We keep track of the current section number in |section_count|, which
  161. is the total number of sections that have started.  Sections which have
  162. been altered by a change file entry have their |changed_section| flag
  163. turned on during the first phase.
  164. @<Global...@>=
  165. boolean change_exists; /* has any section changed? */
  166. @ The other large memory area in \.{CWEAVE} keeps the cross-reference data.
  167. All uses of the name |p| are recorded in a linked list beginning at
  168. |p->xref|, which points into the |xmem| array. The elements of |xmem|
  169. are structures consisting of an integer, |num|, and a pointer |xlink|
  170. to another element of |xmem|.  If |x=p->xref| is a pointer into |xmem|,
  171. the value of |x->num| is either a section number where |p| is used,
  172. or |cite_flag| plus a section number where |p| is mentioned,
  173. or |def_flag| plus a section number where |p| is defined;
  174. and |x->xlink| points to the next such cross-reference for |p|,
  175. if any. This list of cross-references is in decreasing order by
  176. section number. The next unused slot in |xmem| is |xref_ptr|.
  177. The linked list ends at |&xmem[0]|.
  178. The global variable |xref_switch| is set either to |def_flag| or to zero,
  179. depending on whether the next cross-reference to an identifier is to be
  180. underlined or not in the index. This switch is set to |def_flag| when
  181. \.{@@!} or \.{@@d} is scanned, and it is cleared to zero when
  182. the next identifier or index entry cross-reference has been made.
  183. Similarly, the global variable |section_xref_switch| is either
  184. |def_flag| or |cite_flag| or zero, depending
  185. on whether a section name is being defined, cited or used in \CEE/ text.
  186. @<Type...@>=
  187. typedef struct xref_info {
  188.   sixteen_bits num; /* section number plus zero or |def_flag| */
  189.   struct xref_info *xlink; /* pointer to the previous cross-reference */
  190. } xref_info;
  191. typedef xref_info *xref_pointer;
  192. @ @<Global...@>=
  193. xref_info xmem[max_refs]; /* contains cross-reference information */
  194. xref_pointer xmem_end = xmem+max_refs-1;
  195. xref_pointer xref_ptr; /* the largest occupied position in |xmem| */
  196. sixteen_bits xref_switch,section_xref_switch; /* either zero or |def_flag| */
  197. @ A section that is used for multi-file output (with the \.{@@(} feature)
  198. has a special first cross-reference whose |num| field is |file_flag|.
  199. @d file_flag (3*cite_flag)
  200. @d def_flag (2*cite_flag)
  201. @d cite_flag 10240 /* must be strictly larger than |max_sections| */
  202. @d xref equiv_or_xref
  203. @<Set init...@>=
  204. xref_ptr=xmem; name_dir->xref=(char*)xmem; xref_switch=0; section_xref_switch=0;
  205. xmem->num=0; /* sentinel value */
  206. @ A new cross-reference for an identifier is formed by calling |new_xref|,
  207. which discards duplicate entries and ignores non-underlined references
  208. to one-letter identifiers or \CEE/'s reserved words.
  209. If the user has sent the |no_xref| flag (the \.{-x} option of the command line),
  210. it is unnecessary to keep track of cross-references for identifiers.
  211. If one were careful, one could probably make more changes around section
  212. 100 to avoid a lot of identifier looking up.
  213. @d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference");
  214.   else (++xref_ptr)->num=c;
  215. @d no_xref (flags['x']==0)
  216. @d make_xrefs flags['x'] /* should cross references be output? */
  217. @d is_tiny(p) ((p+1)->byte_start==(p)->byte_start+1)
  218. new_xref(p)
  219. name_pointer p;
  220.   xref_pointer q; /* pointer to previous cross-reference */
  221.   sixteen_bits m, n; /* new and previous cross-reference value */
  222.   if (no_xref) return;
  223.   if ((unindexed(p) || is_tiny(p)) && xref_switch==0) return;
  224.   m=section_count+xref_switch; xref_switch=0; q=(xref_pointer)p->xref;
  225.   if (q != xmem) {
  226.     n=q->num;
  227.     if (n==m || n==m+def_flag) return;
  228.     else if (m==n+def_flag) {
  229.         q->num=m; return;
  230.     }
  231.   append_xref(m); xref_ptr->xlink=q; p->xref=(char*)xref_ptr;
  232. @ The cross-reference lists for section names are slightly different.
  233. Suppose that a section name is defined in sections $m_1$, \dots,
  234. $m_k$, cited in sections $n_1$, \dots, $n_l$, and used in sections
  235. $p_1$, \dots, $p_j$.  Then its list will contain $m_1+|def_flag|$,
  236. \dots, $m_k+|def_flag|$, $n_1+|cite_flag|$, \dots,
  237. $n_l+|cite_flag|$, $p_1$, \dots, $p_j$, in this order.
  238. Although this method of storage take quadratic time on the length of
  239. the list, under foreseeable uses of \.{CWEAVE} this inefficiency is
  240. insignificant.
  241. new_section_xref(p)
  242. name_pointer p;
  243.   xref_pointer q,r; /* pointers to previous cross-references */
  244.   q=(xref_pointer)p->xref; r=xmem;
  245.   if (q>xmem)
  246.         while (q->num>section_xref_switch) {r=q; q=q->xlink;}
  247.   if (r->num==section_count+section_xref_switch)
  248.         return; /* don't duplicate entries */
  249.   append_xref(section_count+section_xref_switch);
  250.   xref_ptr->xlink=q; section_xref_switch=0;
  251.   if (r==xmem) p->xref=(char*)xref_ptr;
  252.   else r->xlink=xref_ptr;
  253. @ The cross-reference list for a section name may also begin with
  254. |file_flag|. Here's how that flag gets put~in.
  255. set_file_flag(p)
  256. name_pointer p;
  257.   xref_pointer q;
  258.   q=(xref_pointer)p->xref;
  259.   if (q->num==file_flag) return;
  260.   append_xref(file_flag);
  261.   xref_ptr->xlink = q;
  262.   p->xref = (char *)xref_ptr;
  263. @ A third large area of memory is used for sixteen-bit `tokens', which appear
  264. in short lists similar to the strings of characters in |byte_mem|. Token lists
  265. are used to contain the result of \CEE/ code translated into \TEX/ form;
  266. further details about them will be explained later. A |text_pointer| variable
  267. is an index into |tok_start|.
  268. @<Typed...@>=
  269. typedef sixteen_bits token;
  270. typedef token *token_pointer;
  271. typedef token_pointer *text_pointer;
  272. @ The first position of |tok_mem|
  273. that is unoccupied by replacement text is called |tok_ptr|, and the first
  274. unused location of |tok_start| is called |text_ptr|.
  275. Thus, we usually have |*text_ptr==tok_ptr|.
  276. @<Global...@>=
  277. token tok_mem[max_toks]; /* tokens */
  278. token_pointer tok_mem_end = tok_mem+max_toks-1; /* end of |tok_mem| */
  279. token_pointer tok_start[max_texts]; /* directory into |tok_mem| */
  280. token_pointer tok_ptr; /* first unused position in |tok_mem| */
  281. text_pointer text_ptr; /* first unused position in |tok_start| */
  282. text_pointer tok_start_end = tok_start+max_texts-1; /* end of |tok_start| */
  283. token_pointer max_tok_ptr; /* largest value of |tok_ptr| */
  284. text_pointer max_text_ptr; /* largest value of |text_ptr| */
  285. @ @<Set init...@>=
  286. tok_ptr=tok_mem+1; text_ptr=tok_start+1; tok_start[0]=tok_mem+1;
  287. tok_start[1]=tok_mem+1;
  288. max_tok_ptr=tok_mem+1; max_text_ptr=tok_start+1;
  289. @ Here are the three procedures needed to complete |id_lookup|:
  290. int names_match(p,first,l,t)
  291. name_pointer p; /* points to the proposed match */
  292. char *first; /* position of first character of string */
  293. int l; /* length of identifier */
  294. eight_bits t; /* desired ilk */
  295.   if (length(p)!=l) return 0;
  296.   if (p->ilk!=t && !(t==normal && abnormal(p))) return 0;
  297.   return !strncmp(first,p->byte_start,l);
  298. init_p(p,t)
  299. name_pointer p;
  300. eight_bits t;
  301.   p->ilk=t; p->xref=(char*)xmem;
  302. init_node(p)
  303. name_pointer p;
  304.   p->xref=(char*)xmem;
  305. @ We have to get \CEE/'s
  306. reserved words into the hash table, and the simplest way to do this is
  307. to insert them every time \.{CWEAVE} is run.  Fortunately there are relatively
  308. few reserved words. (Some of these are not strictly ``reserved,'' but
  309. are defined in header files of the ISO Standard \CEE/ Library.)
  310. @^reserved words@>
  311. @<Store all the reserved words@>=
  312. id_lookup("asm",NULL,sizeof_like);
  313. id_lookup("auto",NULL,int_like);
  314. id_lookup("break",NULL,case_like);
  315. id_lookup("case",NULL,case_like);
  316. id_lookup("catch",NULL,catch_like);
  317. id_lookup("char",NULL,raw_int);
  318. id_lookup("class",NULL,struct_like);
  319. id_lookup("clock_t",NULL,raw_int);
  320. id_lookup("const",NULL,const_like);
  321. id_lookup("continue",NULL,case_like);
  322. id_lookup("default",NULL,case_like);
  323. id_lookup("define",NULL,define_like);
  324. id_lookup("defined",NULL,sizeof_like);
  325. id_lookup("delete",NULL,sizeof_like);
  326. id_lookup("div_t",NULL,raw_int);
  327. id_lookup("do",NULL,do_like);
  328. id_lookup("double",NULL,raw_int);
  329. id_lookup("elif",NULL,if_like);
  330. id_lookup("else",NULL,else_like);
  331. id_lookup("endif",NULL,if_like);
  332. id_lookup("enum",NULL,struct_like);
  333. id_lookup("error",NULL,if_like);
  334. id_lookup("extern",NULL,int_like);
  335. id_lookup("FILE",NULL,raw_int);
  336. id_lookup("float",NULL,raw_int);
  337. id_lookup("for",NULL,for_like);
  338. id_lookup("fpos_t",NULL,raw_int);
  339. id_lookup("friend",NULL,int_like);
  340. id_lookup("goto",NULL,case_like);
  341. id_lookup("if",NULL,if_like);
  342. id_lookup("ifdef",NULL,if_like);
  343. id_lookup("ifndef",NULL,if_like);
  344. id_lookup("include",NULL,if_like);
  345. id_lookup("inline",NULL,int_like);
  346. id_lookup("int",NULL,raw_int);
  347. id_lookup("jmp_buf",NULL,raw_int);
  348. id_lookup("ldiv_t",NULL,raw_int);
  349. id_lookup("line",NULL,if_like);
  350. id_lookup("long",NULL,raw_int);
  351. id_lookup("new",NULL,new_like);
  352. id_lookup("NULL",NULL,quoted);
  353. id_lookup("offsetof",NULL,sizeof_like);
  354. id_lookup("operator",NULL,operator_like);
  355. id_lookup("pragma",NULL,if_like);
  356. id_lookup("private",NULL,public_like);
  357. id_lookup("protected",NULL,public_like);
  358. id_lookup("ptrdiff_t",NULL,raw_int);
  359. id_lookup("public",NULL,public_like);
  360. id_lookup("register",NULL,int_like);
  361. id_lookup("return",NULL,case_like);
  362. id_lookup("short",NULL,raw_int);
  363. id_lookup("sig_atomic_t",NULL,raw_int);
  364. id_lookup("signed",NULL,raw_int);
  365. id_lookup("size_t",NULL,raw_int);
  366. id_lookup("sizeof",NULL,sizeof_like);
  367. id_lookup("static",NULL,int_like);
  368. id_lookup("struct",NULL,struct_like);
  369. id_lookup("switch",NULL,for_like);
  370. id_lookup("template",NULL,int_like);
  371. id_lookup("TeX",NULL,custom);
  372. id_lookup("this",NULL,quoted);
  373. id_lookup("throw",NULL,case_like);
  374. id_lookup("time_t",NULL,raw_int);
  375. id_lookup("try",NULL,else_like);
  376. id_lookup("typedef",NULL,typedef_like);
  377. id_lookup("undef",NULL,if_like);
  378. id_lookup("union",NULL,struct_like);
  379. id_lookup("unsigned",NULL,raw_int);
  380. id_lookup("va_dcl",NULL,decl); /* Berkeley's variable-arg-list convention */
  381. id_lookup("va_list",NULL,raw_int); /* ditto */
  382. id_lookup("virtual",NULL,int_like);
  383. id_lookup("void",NULL,raw_int);
  384. id_lookup("volatile",NULL,const_like);
  385. id_lookup("wchar_t",NULL,raw_int);
  386. id_lookup("while",NULL,for_like);
  387. @* Lexical scanning.
  388. Let us now consider the subroutines that read the \.{CWEB} source file
  389. and break it into meaningful units. There are four such procedures:
  390. One simply skips to the next `\.{@@\ }' or `\.{@@*}' that begins a
  391. section; another passes over the \TEX/ text at the beginning of a
  392. section; the third passes over the \TEX/ text in a \CEE/ comment;
  393. and the last, which is the most interesting, gets the next token of
  394. a \CEE/ text.  They all use the pointers |limit| and |loc| into
  395. the line of input currently being studied.
  396. @ Control codes in \.{CWEB}, which begin with `\.{@@}', are converted
  397. into a numeric code designed to simplify \.{CWEAVE}'s logic; for example,
  398. larger numbers are given to the control codes that denote more significant
  399. milestones, and the code of |new_section| should be the largest of
  400. all. Some of these numeric control codes take the place of |char|
  401. control codes that will not otherwise appear in the output of the
  402. scanning routines.
  403. @^ASCII code dependencies@>
  404. @d ignore 00 /* control code of no interest to \.{CWEAVE} */
  405. @d verbatim 02 /* takes the place of extended ASCII \.{\char2} */
  406. @d begin_short_comment 03 /* \CPLUSPLUS/ short comment */
  407. @d begin_comment '\t' /* tab marks will not appear */
  408. @d underline '\n' /* this code will be intercepted without confusion */
  409. @d noop 0177 /* takes the place of ASCII delete */
  410. @d xref_roman 0203 /* control code for `\.{@@\^}' */
  411. @d xref_wildcard 0204 /* control code for `\.{@@:}' */
  412. @d xref_typewriter 0205 /* control code for `\.{@@.}' */
  413. @d TeX_string 0206 /* control code for `\.{@@t}' */
  414. @f TeX_string TeX
  415. @d ord 0207 /* control code for `\.{@@'}' */
  416. @d join 0210 /* control code for `\.{@@\&}' */
  417. @d thin_space 0211 /* control code for `\.{@@,}' */
  418. @d math_break 0212 /* control code for `\.{@@\v}' */
  419. @d line_break 0213 /* control code for `\.{@@/}' */
  420. @d big_line_break 0214 /* control code for `\.{@@\#}' */
  421. @d no_line_break 0215 /* control code for `\.{@@+}' */
  422. @d pseudo_semi 0216 /* control code for `\.{@@;}' */
  423. @d macro_arg_open 0220 /* control code for `\.{@@[}' */
  424. @d macro_arg_close 0221 /* control code for `\.{@@]}' */
  425. @d trace 0222 /* control code for `\.{@@0}', `\.{@@1}' and `\.{@@2}' */
  426. @d translit_code 0223 /* control code for `\.{@@l}' */
  427. @d output_defs_code 0224 /* control code for `\.{@@h}' */
  428. @d format_code 0225 /* control code for `\.{@@f}' and `\.{@@s}' */
  429. @d definition 0226 /* control code for `\.{@@d}' */
  430. @d begin_C 0227 /* control code for `\.{@@c}' */
  431. @d section_name 0230 /* control code for `\.{@@<}' */
  432. @d new_section 0231 /* control code for `\.{@@\ }' and `\.{@@*}' */
  433. @ Control codes are converted to \.{CWEAVE}'s internal
  434. representation by means of the table |ccode|.
  435. @<Global...@>=
  436. eight_bits ccode[256]; /* meaning of a char following \.{@@} */
  437. @ @<Set ini...@>=
  438. {int c; for (c=0; c<256; c++) ccode[c]=0;}
  439. ccode[' ']=ccode['\t']=ccode['\n']=ccode['\v']=ccode['\r']=ccode['\f']
  440.    =ccode['*']=new_section;
  441. ccode['@@']='@@'; /* `quoted' at sign */
  442. ccode['=']=verbatim;
  443. ccode['d']=ccode['D']=definition;
  444. ccode['f']=ccode['F']=ccode['s']=ccode['S']=format_code;
  445. ccode['c']=ccode['C']=ccode['p']=ccode['P']=begin_C;
  446. ccode['t']=ccode['T']=TeX_string;
  447. ccode['l']=ccode['L']=translit_code;
  448. ccode['q']=ccode['Q']=noop;
  449. ccode['h']=ccode['H']=output_defs_code;
  450. ccode['&']=join; ccode['<']=ccode['(']=section_name;
  451. ccode['!']=underline; ccode['^']=xref_roman;
  452. ccode[':']=xref_wildcard; ccode['.']=xref_typewriter; ccode[',']=thin_space;
  453. ccode['|']=math_break; ccode['/']=line_break; ccode['#']=big_line_break;
  454. ccode['+']=no_line_break; ccode[';']=pseudo_semi;
  455. ccode['[']=macro_arg_open; ccode[']']=macro_arg_close;
  456. ccode['\'']=ord;
  457. @<Special control codes for debugging@>@;
  458. @ Users can write
  459. \.{@@2}, \.{@@1}, and \.{@@0} to turn tracing fully on, partly on,
  460. and off, respectively.
  461. @<Special control codes...@>=
  462. ccode['0']=ccode['1']=ccode['2']=trace;
  463. @ The |skip_limbo| routine is used on the first pass to skip through
  464. portions of the input that are not in any sections, i.e., that precede
  465. the first section. After this procedure has been called, the value of
  466. |input_has_ended| will tell whether or not a section has actually been found.
  467. There's a complication that we will postpone until later: If the \.{@@s}
  468. operation appears in limbo, we want to use it to adjust the default
  469. interpretation of identifiers.
  470. @<Predec...@>=
  471. void   skip_limbo();
  472. skip_limbo() {
  473.   while(1) {
  474.     if (loc>limit && get_line()==0) return;
  475.     *(limit+1)='@@';
  476.     while (*loc!='@@') loc++; /* look for '@@', then skip two chars */
  477.     if (loc++ <=limit) { int c=ccode[(eight_bits)*loc++];
  478.       if (c==new_section) return;
  479.       if (c==noop) skip_restricted();
  480.       else if (c==format_code) @<Process simple format in limbo@>;
  481.     }
  482. @ The |skip_TeX| routine is used on the first pass to skip through
  483. the \TEX/ code at the beginning of a section. It returns the next
  484. control code or `\.{\v}' found in the input. A |new_section| is
  485. assumed to exist at the very end of the file.
  486. @f skip_TeX TeX
  487. unsigned
  488. skip_TeX() /* skip past pure \TEX/ code */
  489.   while (1) {
  490.     if (loc>limit && get_line()==0) return(new_section);
  491.     *(limit+1)='@@';
  492.     while (*loc!='@@' && *loc!='|') loc++;
  493.     if (*loc++ =='|') return('|');
  494.     if (loc<=limit) return(ccode[(eight_bits)*(loc++)]);
  495. @*1 Inputting the next token.
  496. As stated above, \.{CWEAVE}'s most interesting lexical scanning routine is the
  497. |get_next| function that inputs the next token of \CEE/ input. However,
  498. |get_next| is not especially complicated.
  499. The result of |get_next| is either a |char| code for some special character,
  500. or it is a special code representing a pair of characters (e.g., `\.{!=}'),
  501. or it is the numeric value computed by the |ccode|
  502. table, or it is one of the following special codes:
  503. \yskip\hang |identifier|: In this case the global variables |id_first| and
  504. |id_loc| will have been set to the beginning and ending-plus-one locations
  505. in the buffer, as required by the |id_lookup| routine.
  506. \yskip\hang |string|: The string will have been copied into the array
  507. |section_text|; |id_first| and |id_loc| are set as above (now they are
  508. pointers into |section_text|).
  509. \yskip\hang |constant|: The constant is copied into |section_text|, with
  510. slight modifications; |id_first| and |id_loc| are set.
  511. \yskip\noindent Furthermore, some of the control codes cause
  512. |get_next| to take additional actions:
  513. \yskip\hang |xref_roman|, |xref_wildcard|, |xref_typewriter|, |TeX_string|,
  514. |verbatim|: The values of |id_first| and |id_loc| will have been set to
  515. the beginning and ending-plus-one locations in the buffer.
  516. \yskip\hang |section_name|: In this case the global variable |cur_section| will
  517. point to the |byte_start| entry for the section name that has just been scanned.
  518. The value of |cur_section_char| will be |'('| if the section name was
  519. preceded by \.{@@(} instead of \.{@@<}.
  520. \yskip\noindent If |get_next| sees `\.{@@!}'
  521. it sets |xref_switch| to |def_flag| and goes on to the next token.
  522. @d constant 0200 /* \CEE/ constant */
  523. @d string 0201 /* \CEE/ string */
  524. @d identifier 0202 /* \CEE/ identifier or reserved word */
  525. @<Global...@>=
  526. name_pointer cur_section; /* name of section just scanned */
  527. char cur_section_char; /* the character just before that name */
  528. @ @<Include...@>=
  529. #include <ctype.h> /* definition of |isalpha|, |isdigit| and so on */
  530. #include <stdlib.h> /* definition of |exit| */
  531. @ As one might expect, |get_next| consists mostly of a big switch
  532. that branches to the various special cases that can arise.
  533. @d isxalpha(c) ((c)=='_') /* non-alpha character allowed in identifier */
  534. @d ishigh(c) ((eight_bits)(c)>0177)
  535. @^high-bit character handling@>
  536. @<Predecl...@>=
  537. eight_bits get_next();
  538. eight_bits
  539. get_next() /* produces the next input token */
  540. {@+eight_bits c; /* the current character */
  541.   while (1) {
  542.     @<Check if we're at the end of a preprocessor command@>;
  543.     if (loc>limit && get_line()==0) return(new_section);
  544.     c=*(loc++);
  545.     if (xisdigit(c) || c=='\\' || c=='.') @<Get a constant@>@;
  546.     else if (c=='\'' || c=='"' || (c=='L'&&(*loc=='\'' || *loc=='"'))@|
  547.            || (c=='<' && sharp_include_line==1))
  548.         @<Get a string@>@;
  549.     else if (xisalpha(c) || isxalpha(c) || ishigh(c))
  550.       @<Get an identifier@>@;
  551.     else if (c=='@@') @<Get control code and possible section name@>@;
  552.     else if (xisspace(c)) continue; /* ignore spaces and tabs */
  553.     if (c=='#' && loc==buffer+1) @<Raise preprocessor flag@>;
  554.     mistake: @<Compress two-symbol operator@>@;
  555.     return(c);
  556. @ Because preprocessor commands do not fit in with the rest of the syntax
  557. of \CEE/,
  558. we have to deal with them separately.  One solution is to enclose such
  559. commands between special markers.  Thus, when a \.\# is seen as the
  560. first character of a line, |get_next| returns a special code
  561. |left_preproc| and raises a flag |preprocessing|.
  562. We can use the same internal code number for |left_preproc| as we do
  563. for |ord|, since |get_next| changes |ord| into a string.
  564. @d left_preproc ord /* begins a preprocessor command */
  565. @d right_preproc 0217 /* ends a preprocessor command */
  566. @<Glob...@>=
  567. boolean preprocessing=0; /* are we scanning a preprocessor command? */
  568. @ @<Raise prep...@>= {
  569.   preprocessing=1;
  570.   @<Check if next token is |include|@>;
  571.   return (left_preproc);
  572. @ An additional complication is the freakish use of \.< and \.> to delimit
  573. a file name in lines that start with \.{\#include}.  We must treat this file
  574. name as a string.
  575. @<Glob...@>=
  576. boolean sharp_include_line=0; /* are we scanning a |#include| line? */
  577. @ @<Check if next token is |include|@>=
  578. while (loc<=buffer_end-7 && xisspace(*loc)) loc++;
  579. if (loc<=buffer_end-6 && strncmp(loc,"include",7)==0) sharp_include_line=1;
  580. @ When we get to the end of a preprocessor line,
  581. we lower the flag and send a code |right_preproc|, unless
  582. the last character was a \.\\.
  583. @<Check if we're at...@>=
  584.   while (loc==limit-1 && preprocessing && *loc=='\\')
  585.     if (get_line()==0) return(new_section); /* still in preprocessor mode */
  586.   if (loc>=limit && preprocessing) {
  587.     preprocessing=sharp_include_line=0;
  588.     return(right_preproc);
  589. @ The following code assigns values to the combinations \.{++},
  590. \.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{\v\v}, and
  591. \.{\&\&}, and to the \CPLUSPLUS/
  592. combinations \.{...}, \.{::}, \.{.*} and \.{->*}.
  593. The compound assignment operators (e.g., \.{+=}) are
  594. treated as separate tokens.
  595. @d compress(c) if (loc++<=limit) return(c)
  596. @<Compress tw...@>=
  597. switch(c) {
  598.   case '/': if (*loc=='*') {compress(begin_comment);}
  599.     else if (*loc=='/') compress(begin_short_comment); break;
  600.   case '+': if (*loc=='+') compress(plus_plus); break;
  601.   case '-': if (*loc=='-') {compress(minus_minus);}
  602.     else if (*loc=='>') if (*(loc+1)=='*') {loc++; compress(minus_gt_ast);}
  603.                         else compress(minus_gt); break;
  604.   case '.': if (*loc=='*') {compress(period_ast);}
  605.             else if (*loc=='.' && *(loc+1)=='.') {
  606.               loc++; compress(dot_dot_dot);
  607.             }
  608.             break;
  609.   case ':': if (*loc==':') compress(colon_colon); break;
  610.   case '=': if (*loc=='=') compress(eq_eq); break;
  611.   case '>': if (*loc=='=') {compress(gt_eq);}
  612.     else if (*loc=='>') compress(gt_gt); break;
  613.   case '<': if (*loc=='=') {compress(lt_eq);}
  614.     else if (*loc=='<') compress(lt_lt); break;
  615.   case '&': if (*loc=='&') compress(and_and); break;
  616.   case '|': if (*loc=='|') compress(or_or); break;
  617.   case '!': if (*loc=='=') compress(not_eq); break;
  618. @ @<Get an identifier@>= {
  619.   id_first=--loc;
  620.   while (isalpha(*++loc) || isdigit(*loc) || isxalpha(*loc) || ishigh(*loc));
  621.   id_loc=loc; return(identifier);
  622. @ Different conventions are followed by \TEX/ and \CEE/ to express octal
  623. and hexadecimal numbers; it is reasonable to stick to each convention
  624. within its realm.  Thus the \CEE/ part of a \.{CWEB} file has octals
  625. introduced by \.0 and hexadecimals by \.{0x}, but \.{CWEAVE} will print
  626. in italics or typewriter font, respectively, and introduced by single
  627. or double quotes.  In order to simplify the \TEX/ macro used to print
  628. such constants, we replace some of the characters.
  629. Notice that in this section and the next, |id_first| and |id_loc|
  630. are pointers into the array |section_text|, not into |buffer|.
  631. @<Get a constant@>= {
  632.   id_first=id_loc=section_text+1;
  633.   if (*(loc-1)=='\\') {*id_loc++='~';
  634.   while (xisdigit(*loc)) *id_loc++=*loc++;} /* octal constant */
  635.   else if (*(loc-1)=='0') {
  636.     if (*loc=='x' || *loc=='X') {*id_loc++='^'; loc++;
  637.       while (xisxdigit(*loc)) *id_loc++=*loc++;} /* hex constant */
  638.     else if (xisdigit(*loc)) {*id_loc++='~';
  639.       while (xisdigit(*loc)) *id_loc++=*loc++;} /* octal constant */
  640.     else goto dec; /* decimal constant */
  641.   else { /* decimal constant */
  642.     if (*(loc-1)=='.' && !xisdigit(*loc)) goto mistake; /* not a constant */
  643.     dec: *id_loc++=*(loc-1);
  644.     while (xisdigit(*loc) || *loc=='.') *id_loc++=*loc++;
  645.     if (*loc=='e' || *loc=='E') { /* float constant */
  646.       *id_loc++='_'; loc++;
  647.       if (*loc=='+' || *loc=='-') *id_loc++=*loc++;
  648.       while (xisdigit(*loc)) *id_loc++=*loc++;
  649.     }
  650.   while (*loc=='u' || *loc=='U' || *loc=='l' || *loc=='L'
  651.          || *loc=='f' || *loc=='F') {
  652.     *id_loc++='$'; *id_loc++=toupper(*loc++);
  653.   return(constant);
  654. @ \CEE/ strings and character constants, delimited by double and single
  655. quotes, respectively, can contain newlines or instances of their own
  656. delimiters if they are protected by a backslash.  We follow this
  657. convention, but do not allow the string to be longer than |longest_name|.
  658. @<Get a string@>= {
  659.   char delim = c; /* what started the string */
  660.   id_first = section_text+1;
  661.   id_loc = section_text;
  662.   if (delim=='\'' && *(loc-2)=='@@') {*++id_loc='@@'; *++id_loc='@@';}
  663.   *++id_loc=delim;
  664.   if (delim=='L') { /* wide character constant */
  665.     delim=*loc++; *++id_loc=delim;
  666.   if (delim=='<') delim='>'; /* for file names in |#include| lines */
  667.   while (1) {
  668.     if (loc>=limit) {
  669.       if(*(limit-1)!='\\') {
  670.         err_print("! String didn't end"); loc=limit; break;
  671. @.String didn't end@>
  672.       }
  673.       if(get_line()==0) {
  674.         err_print("! Input ended in middle of string"); loc=buffer; break;
  675. @.Input ended in middle of string@>
  676.       }
  677.     }
  678.     if ((c=*loc++)==delim) {
  679.       if (++id_loc<=section_text_end) *id_loc=c;
  680.       break;
  681.     }
  682.     if (c=='\\') if (loc>=limit) continue;
  683.       else if (++id_loc<=section_text_end) {
  684.         *id_loc = '\\'; c=*loc++;
  685.       }
  686.     if (++id_loc<=section_text_end) *id_loc=c;
  687.   if (id_loc>=section_text_end) {
  688.     printf("\n! String too long: ");
  689. @.String too long@>
  690.     term_write(section_text+1,25);
  691.     printf("..."); mark_error;
  692.   id_loc++;
  693.   return(string);
  694. @ After an \.{@@} sign has been scanned, the next character tells us
  695. whether there is more work to do.
  696. @<Get control code and possible section name@>= {
  697.   c=*loc++;
  698.   switch(ccode[(eight_bits)c]) {
  699.     case translit_code: err_print("! Use @@l in limbo only"); continue;
  700. @.Use @@l in limbo...@>
  701.     case underline: xref_switch=def_flag; continue;
  702.     case trace: tracing=c-'0'; continue;
  703.     case xref_roman: case xref_wildcard: case xref_typewriter:
  704.     case noop: case TeX_string: c=ccode[c]; skip_restricted(); return(c);
  705.     case section_name:
  706.       @<Scan the section name and make |cur_section| point to it@>;
  707.     case verbatim: @<Scan a verbatim string@>;
  708.     case ord: @<Get a string@>;
  709.     default: return(ccode[(eight_bits)c]);
  710. @ The occurrence of a section name sets |xref_switch| to zero,
  711. because the section name might (for example) follow \&{int}.
  712. @<Scan the section name...@>= {
  713.   char *k; /* pointer into |section_text| */
  714.   cur_section_char=*(loc-1);
  715.   @<Put section name into |section_text|@>;
  716.   if (k-section_text>3 && strncmp(k-2,"...",3)==0)
  717.         cur_section=section_lookup(section_text+1,k-3,1); /* 1 indicates a prefix */
  718.   else cur_section=section_lookup(section_text+1,k,0);
  719.   xref_switch=0; return(section_name);
  720. @ Section names are placed into the |section_text| array with consecutive spaces,
  721. tabs, and carriage-returns replaced by single spaces. There will be no
  722. spaces at the beginning or the end. (We set |section_text[0]=' '| to facilitate
  723. this, since the |section_lookup| routine uses |section_text[1]| as the first
  724. character of the name.)
  725. @<Set init...@>=section_text[0]=' ';
  726. @ @<Put section name...@>=
  727. k=section_text;
  728. while (1) {
  729.   if (loc>limit && get_line()==0) {
  730.     err_print("! Input ended in section name");
  731. @.Input ended in section name@>
  732.     loc=buffer+1; break;
  733.   c=*loc;
  734.   @<If end of name or erroneous control code, |break|@>;
  735.   loc++; if (k<section_text_end) k++;
  736.   if (xisspace(c)) {
  737.     c=' '; if (*(k-1)==' ') k--;
  738. *k=c;
  739. if (k>=section_text_end) {
  740.   printf("\n! Section name too long: ");
  741. @.Section name too long@>
  742.   term_write(section_text+1,25);
  743.   printf("..."); mark_harmless;
  744. if (*k==' ' && k>section_text) k--;
  745. @ @<If end of name...@>=
  746. if (c=='@@') {
  747.   c=*(loc+1);
  748.   if (c=='>') {
  749.     loc+=2; break;
  750.   if (ccode[(eight_bits)c]==new_section) {
  751.     err_print("! Section name didn't end"); break;
  752. @.Section name didn't end@>
  753.   if (c!='@@') {
  754.     err_print("! Control codes are forbidden in section name"); break;
  755. @.Control codes are forbidden...@>
  756.   *(++k)='@@'; loc++; /* now |c==*loc| again */
  757. @ This function skips over a restricted context at relatively high speed.
  758. @<Predecl...@>=
  759. void skip_restricted();
  760. skip_restricted()
  761.   id_first=loc; *(limit+1)='@@';
  762. false_alarm:
  763.   while (*loc!='@@') loc++;
  764.   id_loc=loc;
  765.   if (loc++>limit) {
  766.     err_print("! Control text didn't end"); loc=limit;
  767. @.Control text didn't end@>
  768.   else {
  769.     if (*loc=='@@'&&loc<=limit) {loc++; goto false_alarm;}
  770.     if (*loc++!='>')
  771.       err_print("! Control codes are forbidden in control text");
  772. @.Control codes are forbidden...@>
  773. @ At the present point in the program we
  774. have |*(loc-1)==verbatim|; we set |id_first| to the beginning
  775. of the string itself, and |id_loc| to its ending-plus-one location in the
  776. buffer.  We also set |loc| to the position just after the ending delimiter.
  777. @<Scan a verbatim string@>= {
  778.   id_first=loc++; *(limit+1)='@@'; *(limit+2)='>';
  779.   while (*loc!='@@' || *(loc+1)!='>') loc++;
  780.   if (loc>=limit) err_print("! Verbatim string didn't end");
  781. @.Verbatim string didn't end@>
  782.   id_loc=loc; loc+=2;
  783.   return (verbatim);
  784. @** Phase one processing.
  785. We now have accumulated enough subroutines to make it possible to carry out
  786. \.{CWEAVE}'s first pass over the source file. If everything works right,
  787. both phase one and phase two of \.{CWEAVE} will assign the same numbers to
  788. sections, and these numbers will agree with what \.{CTANGLE} does.
  789. The global variable |next_control| often contains the most recent output of
  790. |get_next|; in interesting cases, this will be the control code that
  791. ended a section or part of a section.
  792. @<Global...@>=
  793. eight_bits next_control; /* control code waiting to be acting upon */
  794. @ The overall processing strategy in phase one has the following
  795. straightforward outline.
  796. @<Predecl...@>=
  797. void phase_one();
  798. phase_one() {
  799.   phase=1; reset_input(); section_count=0;
  800.   skip_limbo(); change_exists=0;
  801.   while (!input_has_ended)
  802.     @<Store cross-reference data for the current section@>;
  803.   changed_section[section_count]=change_exists;
  804.     /* the index changes if anything does */
  805.   phase=2; /* prepare for second phase */
  806.   @<Print error messages about unused or undefined section names@>;
  807. @ @<Store cross-reference data...@>=
  808.   if (++section_count==max_sections) overflow("section number");
  809.   changed_section[section_count]=changing;
  810.      /* it will become 1 if any line changes */
  811.   if (*(loc-1)=='*' && show_progress) {
  812.     printf("*%d",section_count);
  813.     update_terminal; /* print a progress report */
  814.   @<Store cross-references in the \TEX/ part of a section@>;
  815.   @<Store cross-references in the definition part of a section@>;
  816.   @<Store cross-references in the \CEE/ part of a section@>;
  817.   if (changed_section[section_count]) change_exists=1;
  818. @ The |C_xref| subroutine stores references to identifiers in
  819. \CEE/ text material beginning with the current value of |next_control|
  820. and continuing until |next_control| is `\.\{' or `\.{\v}', or until the next
  821. ``milestone'' is passed (i.e., |next_control>=format_code|). If
  822. |next_control>=format_code| when |C_xref| is called, nothing will happen;
  823. but if |next_control=='|'| upon entry, the procedure assumes that this is
  824. the `\.{\v}' preceding \CEE/ text that is to be processed.
  825. The parameter |spec_ctrl| is used to change this behavior. In most cases
  826. |C_xref| is called with |spec_ctrl==ignore|, which triggers the default
  827. processing described above. If |spec_ctrl==section_name|, section names will
  828. be gobbled. This is used when \CEE/ text in the \TEX/ part or inside comments
  829. is parsed: It allows for section names to appear in \pb, but these
  830. strings will not be entered into the cross reference lists since they are not
  831. definitions of section names.
  832. The program uses the fact that our internal code numbers satisfy
  833. the relations |xref_roman==identifier+roman| and |xref_wildcard==identifier
  834. +wildcard| and |xref_typewriter==identifier+typewriter| and |normal==0|.
  835. @<Predecl...@>=
  836. void C_xref();
  837. C_xref( spec_ctrl ) /* makes cross-references for \CEE/ identifiers */
  838.   eight_bits spec_ctrl;
  839.   name_pointer p; /* a referenced name */
  840.   while (next_control<format_code || next_control==spec_ctrl) {
  841.     if (next_control>=identifier && next_control<=xref_typewriter) {
  842.       if (next_control>identifier) @<Replace |"@@@@"| by |"@@"| @>@;
  843.       p=id_lookup(id_first, id_loc,next_control-identifier); new_xref(p);
  844.     }
  845.     if (next_control==section_name) {
  846.       section_xref_switch=cite_flag;
  847.       new_section_xref(cur_section);
  848.     }
  849.     next_control=get_next();
  850.     if (next_control=='|' || next_control==begin_comment ||
  851.         next_control==begin_short_comment) return;
  852. @ The |outer_xref| subroutine is like |C_xref| except that it begins
  853. with |next_control!='|'| and ends with |next_control>=format_code|. Thus, it
  854. handles \CEE/ text with embedded comments.
  855. @<Predecl...@>=
  856. void outer_xref();
  857. outer_xref() /* extension of |C_xref| */
  858.   int bal; /* brace level in comment */
  859.   while (next_control<format_code)
  860.     if (next_control!=begin_comment && next_control!=begin_short_comment)
  861.       C_xref(ignore);
  862.     else {
  863.       boolean is_long_comment=(next_control==begin_comment);
  864.       bal=copy_comment(is_long_comment,1); next_control='|';
  865.       while (bal>0) {
  866.         C_xref(section_name); /* do not reference section names in comments */
  867.         if (next_control=='|') bal=copy_comment(is_long_comment,bal);
  868.         else bal=0; /* an error message will occur in phase two */
  869.       }
  870.     }
  871. @ In the \TEX/ part of a section, cross-reference entries are made only for
  872. the identifiers in \CEE/ texts enclosed in \pb, or for control texts
  873. enclosed in \.{@@\^}$\,\ldots\,$\.{@@>} or \.{@@.}$\,\ldots\,$\.{@@>}
  874. or \.{@@:}$\,\ldots\,$\.{@@>}.
  875. @<Store cross-references in the \T...@>=
  876. while (1) {
  877.   switch (next_control=skip_TeX()) {
  878.     case translit_code: err_print("! Use @@l in limbo only"); continue;
  879. @.Use @@l in limbo...@>
  880.     case underline: xref_switch=def_flag; continue;
  881.     case trace: tracing=*(loc-1)-'0'; continue;
  882.     case '|': C_xref(section_name); break;
  883.     case xref_roman: case xref_wildcard: case xref_typewriter:
  884.     case noop: case section_name:
  885.       loc-=2; next_control=get_next(); /* scan to \.{@@>} */
  886.       if (next_control>=xref_roman && next_control<=xref_typewriter) {
  887.         @<Replace |"@@@@"| by |"@@"| @>@;
  888.         new_xref(id_lookup(id_first, id_loc,next_control-identifier));
  889.       }
  890.       break;
  891.   if (next_control>=format_code) break;
  892. @ @<Replace |"@@@@"| by |"@@"| @>=
  893.   char *src=id_first,*dst=id_first;
  894.   while(src<id_loc){
  895.     if(*src=='@@') src++;
  896.     *dst++=*src++;
  897.   id_loc=dst;
  898.   while (dst<src) *dst++=' '; /* clean up in case of error message display */
  899. @ During the definition and \CEE/ parts of a section, cross-references
  900. are made for all identifiers except reserved words. However, the right
  901. identifier in a format definition is not referenced, and the left
  902. identifier is referenced only if it has been explicitly
  903. underlined (preceded by \.{@@!}).
  904. The \TEX/ code in comments is, of course, ignored, except for
  905. \CEE/ portions enclosed in \pb; the text of a section name is skipped
  906. entirely, even if it contains \pb\ constructions.
  907. The variables |lhs| and |rhs| point to the respective identifiers involved
  908. in a format definition.
  909. @<Global...@>=
  910. name_pointer lhs, rhs; /* pointers to |byte_start| for format identifiers */
  911. @ When we get to the following code we have |next_control>=format_code|.
  912. @<Store cross-references in the d...@>=
  913. while (next_control<=definition) { /* |format_code| or |definition| */
  914.   if (next_control==definition) {
  915.     xref_switch=def_flag; /* implied \.{@@!} */
  916.     next_control=get_next();
  917.   } else @<Process a format definition@>;
  918.   outer_xref();
  919. @ Error messages for improper format definitions will be issued in phase
  920. two. Our job in phase one is to define the |ilk| of a properly formatted
  921. identifier, and to remove cross-references to identifiers that we now
  922. discover should be unindexed.
  923. @<Process a form...@>= {
  924.   next_control=get_next();
  925.   if (next_control==identifier) {
  926.     lhs=id_lookup(id_first, id_loc,normal); lhs->ilk=normal;
  927.     if (xref_switch) new_xref(lhs);
  928.     next_control=get_next();
  929.     if (next_control==identifier) {
  930.       rhs=id_lookup(id_first, id_loc,normal);
  931.       lhs->ilk=rhs->ilk;
  932.       if (unindexed(lhs)) { /* retain only underlined entries */
  933.         xref_pointer q,r=NULL;
  934.         for (q=(xref_pointer)lhs->xref;q>xmem;q=q->xlink)
  935.           if (q->num<def_flag)
  936.             if (r) r->xlink=q->xlink;
  937.             else lhs->xref=(char*)q->xlink;
  938.           else r=q;
  939.       }
  940.       next_control=get_next();
  941.     }
  942. @ A much simpler processing of format definitions occurs when the
  943. definition is found in limbo.
  944. @<Process simple format in limbo@>=
  945.   if (get_next()!=identifier)
  946.     err_print("! Missing left identifier of @@s");
  947. @.Missing left identifier...@>
  948.   else {
  949.     lhs=id_lookup(id_first,id_loc,normal);
  950.     if (get_next()!=identifier)
  951.       err_print("! Missing right identifier of @@s");
  952. @.Missing right identifier...@>
  953.     else {
  954.       rhs=id_lookup(id_first,id_loc,normal);
  955.       lhs->ilk=rhs->ilk;
  956.     }
  957. @ Finally, when the \TEX/ and definition parts have been treated, we have
  958. |next_control>=begin_C|.
  959. @<Store cross-references in the \CEE/...@>=
  960. if (next_control<=section_name) {  /* |begin_C| or |section_name| */
  961.   if (next_control==begin_C) section_xref_switch=0;
  962.   else {
  963.     section_xref_switch=def_flag;
  964.     if(cur_section_char=='(' && cur_section!=name_dir)
  965.       set_file_flag(cur_section);
  966.   do {
  967.     if (next_control==section_name && cur_section!=name_dir)
  968.       new_section_xref(cur_section);
  969.     next_control=get_next(); outer_xref();
  970.   } while ( next_control<=section_name);
  971. @ After phase one has looked at everything, we want to check that each
  972. section name was both defined and used.  The variable |cur_xref| will point
  973. to cross-references for the current section name of interest.
  974. @<Global...@>=
  975. xref_pointer cur_xref; /* temporary cross-reference pointer */
  976. boolean an_output; /* did |file_flag| precede |cur_xref|? */
  977. @ The following recursive procedure
  978. walks through the tree of section names and prints out anomalies.
  979. @^recursion@>
  980. @<Predecl...@>=
  981. void section_check();
  982. section_check(p)
  983. name_pointer p; /* print anomalies in subtree |p| */
  984.   if (p) {
  985.     section_check(p->llink);
  986.     cur_xref=(xref_pointer)p->xref;
  987.     if (cur_xref->num==file_flag) {an_output=1; cur_xref=cur_xref->xlink;}
  988.     else an_output=0;
  989.     if (cur_xref->num <def_flag) {
  990.       printf("\n! Never defined: <"); print_section_name(p); putchar('>'); mark_harmless;
  991. @.Never defined: <section name>@>
  992.     }
  993.     while (cur_xref->num >=cite_flag) cur_xref=cur_xref->xlink;
  994.     if (cur_xref==xmem && !an_output) {
  995.       printf("\n! Never used: <"); print_section_name(p); putchar('>'); mark_harmless;
  996. @.Never used: <section name>@>
  997.     }
  998.     section_check(p->rlink);
  999. @ @<Print error messages about un...@>=section_check(root)
  1000. @* Low-level output routines.
  1001. The \TEX/ output is supposed to appear in lines at most |line_length|
  1002. characters long, so we place it into an output buffer. During the output
  1003. process, |out_line| will hold the current line number of the line about to
  1004. be output.
  1005. @<Global...@>=
  1006. char out_buf[line_length+1]; /* assembled characters */
  1007. char *out_ptr; /* just after last character in |out_buf| */
  1008. char *out_buf_end = out_buf+line_length; /* end of |out_buf| */
  1009. int out_line; /* number of next line to be output */
  1010. @ The |flush_buffer| routine empties the buffer up to a given breakpoint,
  1011. and moves any remaining characters to the beginning of the next line.
  1012. If the |per_cent| parameter is 1 a |'%'| is appended to the line
  1013. that is being output; in this case the breakpoint |b| should be strictly
  1014. less than |out_buf_end|. If the |per_cent| parameter is |0|,
  1015. trailing blanks are suppressed.
  1016. The characters emptied from the buffer form a new line of output;
  1017. if the |carryover| parameter is true, a |"%"| in that line will be
  1018. carried over to the next line (so that \TEX/ will ignore the completion
  1019. of commented-out text).
  1020. @d c_line_write(c) fflush(active_file),fwrite(out_buf+1,sizeof(char),c,active_file)
  1021. @d tex_putc(c) putc(c,active_file)
  1022. @d tex_new_line putc('\n',active_file)
  1023. @d tex_printf(c) fprintf(active_file,c)
  1024. flush_buffer(b,per_cent,carryover)
  1025. char *b;  /* outputs from |out_buf+1| to |b|,where |b<=out_ptr| */
  1026. boolean per_cent,carryover;
  1027.   char *j; j=b; /* pointer into |out_buf| */
  1028.   if (! per_cent) /* remove trailing blanks */
  1029.     while (j>out_buf && *j==' ') j--;
  1030.   c_line_write(j-out_buf);
  1031.   if (per_cent) tex_putc('%');
  1032.   tex_new_line; out_line++;
  1033.   if (carryover)
  1034.     while (j>out_buf)
  1035.       if (*j--=='%' && (j==out_buf || *j!='\\')) {
  1036.         *b--='%'; break;
  1037.       }
  1038.   if (b<out_ptr) strncpy(out_buf+1,b+1,out_ptr-b);
  1039.   out_ptr-=b-out_buf;
  1040. @ When we are copying \TEX/ source material, we retain line breaks
  1041. that occur in the input, except that an empty line is not
  1042. output when the \TEX/ source line was nonempty. For example, a line
  1043. of the \TEX/ file that contains only an index cross-reference entry
  1044. will not be copied. The |finish_line| routine is called just before
  1045. |get_line| inputs a new line, and just after a line break token has
  1046. been emitted during the output of translated \CEE/ text.
  1047. finish_line() /* do this at the end of a line */
  1048.   char *k; /* pointer into |buffer| */
  1049.   if (out_ptr>out_buf) flush_buffer(out_ptr,0,0);
  1050.   else {
  1051.     for (k=buffer; k<=limit; k++)
  1052.       if (!(xisspace(*k))) return;
  1053.     flush_buffer(out_buf,0,0);
  1054. @ In particular, the |finish_line| procedure is called near the very
  1055. beginning of phase two. We initialize the output variables in a slightly
  1056. tricky way so that the first line of the output file will be
  1057. `\.{\\input cwebmac}'.
  1058. @<Set init...@>=
  1059. out_ptr=out_buf+1; out_line=1; active_file=tex_file;
  1060. *out_ptr='c'; tex_printf("\\input cwebma");
  1061. @ When we wish to append one character |c| to the output buffer, we write
  1062. `|out(c)|'; this will cause the buffer to be emptied if it was already
  1063. full.  If we want to append more than one character at once, we say
  1064. |out_str(s)|, where |s| is a string containing the characters.
  1065. A line break will occur at a space or after a single-nonletter
  1066. \TEX/ control sequence.
  1067. @d out(c) {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}
  1068. out_str(s) /* output characters from |s| to end of string */
  1069. char *s;
  1070.   while (*s) out(*s++);
  1071. @ The |break_out| routine is called just before the output buffer is about
  1072. to overflow. To make this routine a little faster, we initialize position
  1073. 0 of the output buffer to `\.\\'; this character isn't really output.
  1074. @<Set init...@>=
  1075. out_buf[0]='\\';
  1076. @ A long line is broken at a blank space or just before a backslash that isn't
  1077. preceded by another backslash. In the latter case, a |'%'| is output at
  1078. the break.
  1079. @<Predecl...@>=
  1080. void break_out();
  1081. break_out() /* finds a way to break the output line */
  1082.   char *k=out_ptr; /* pointer into |out_buf| */
  1083.   while (1) {
  1084.     if (k==out_buf) @<Print warning message, break the line, |return|@>;
  1085.     if (*k==' ') {
  1086.       flush_buffer(k,0,1); return;
  1087.     }
  1088.     if (*(k--)=='\\' && *k!='\\') { /* we've decreased |k| */
  1089.       flush_buffer(k,1,1); return;
  1090.     }
  1091. @ We get to this section only in the unusual case that the entire output line
  1092. consists of a string of backslashes followed by a string of nonblank
  1093. non-backslashes. In such cases it is almost always safe to break the
  1094. line by putting a |'%'| just before the last character.
  1095. @<Print warning message...@>=
  1096.   printf("\n! Line had to be broken (output l. %d):\n",out_line);
  1097. @.Line had to be broken@>
  1098.   term_write(out_buf+1, out_ptr-out_buf-1);
  1099.   new_line; mark_harmless;
  1100.   flush_buffer(out_ptr-1,1,1); return;
  1101. @ Here is a macro that outputs a section number in decimal notation.
  1102. The number to be converted by |out_section| is known to be less than
  1103. |def_flag|, so it cannot have more than five decimal digits.  If
  1104. the section is changed, we output `\.{\\*}' just after the number.
  1105. out_section(n)
  1106. sixteen_bits n;
  1107.   char s[6];
  1108.   sprintf(s,"%d",n); out_str(s);
  1109.   if(changed_section[n]) out_str ("\\*");
  1110. @.\\*@>
  1111. @ The |out_name| procedure is used to output an identifier or index
  1112. entry, enclosing it in braces.
  1113. out_name(p)
  1114. name_pointer p;
  1115.   char *k, *k_end=(p+1)->byte_start; /* pointers into |byte_mem| */
  1116.   out('{');
  1117.   for (k=p->byte_start; k<k_end; k++) {
  1118.     if (isxalpha(*k)) out('\\');
  1119.     out(*k);
  1120.   out('}');
  1121. @* Routines that copy \TEX/ material.
  1122. During phase two, we use subroutines |copy_limbo|, |copy_TeX|, and
  1123. |copy_comment| in place of the analogous |skip_limbo|, |skip_TeX|, and
  1124. |skip_comment| that were used in phase one. (Well, |copy_comment|
  1125. was actually written in such a way that it functions as |skip_comment|
  1126. in phase one.)
  1127. The |copy_limbo| routine, for example, takes \TEX/ material that is not
  1128. part of any section and transcribes it almost verbatim to the output file.
  1129. The use of `\.{@@}' signs is severely restricted in such material:
  1130. `\.{@@@@}' pairs are replaced by singletons; `\.{@@l}' and `\.{@@q}' and
  1131. `\.{@@s}' are interpreted.
  1132. copy_limbo()
  1133.   char c;
  1134.   while (1) {
  1135.     if (loc>limit && (finish_line(), get_line()==0)) return;
  1136.     *(limit+1)='@@';
  1137.     while (*loc!='@@') out(*(loc++));
  1138.     if (loc++<=limit) {
  1139.       c=*loc++;
  1140.       if (ccode[(eight_bits)c]==new_section) break;
  1141.       switch (ccode[(eight_bits)c]) {
  1142.         case translit_code: out_str("\\ATL"); break;
  1143. @.\\ATL@>
  1144.         case '@@': out('@@'); break;
  1145.         case noop: skip_restricted(); break;
  1146.         case format_code: if (get_next()==identifier) get_next();
  1147.           if (loc>=limit) get_line(); /* avoid blank lines in output */
  1148.           break; /* the operands of \.{@@s} are ignored on this pass */
  1149.         default: err_print("! Double @@ should be used in limbo");
  1150. @.Double @@ should be used...@>
  1151.         out('@@');
  1152.       }
  1153.     }
  1154. @ The |copy_TeX| routine processes the \TEX/ code at the beginning of a
  1155. section; for example, the words you are now reading were copied in this
  1156. way. It returns the next control code or `\.{\v}' found in the input.
  1157. We don't copy spaces or tab marks into the beginning of a line. This
  1158. makes the test for empty lines in |finish_line| work.
  1159. @ @f copy_TeX TeX
  1160. eight_bits
  1161. copy_TeX()
  1162.   char c; /* current character being copied */
  1163.   while (1) {
  1164.     if (loc>limit && (finish_line(), get_line()==0)) return(new_section);
  1165.     *(limit+1)='@@';
  1166.     while ((c=*(loc++))!='|' && c!='@@') {
  1167.       out(c);
  1168.       if (out_ptr==out_buf+1 && (xisspace(c))) out_ptr--;
  1169.     }
  1170.     if (c=='|') return('|');
  1171.     if (loc<=limit) return(ccode[(eight_bits)*(loc++)]);
  1172. @ The |copy_comment| function issues a warning if more braces are opened than
  1173. closed, and in the case of a more serious error it supplies enough
  1174. braces to keep \TEX/ from complaining about unbalanced braces.
  1175. Instead of copying the \TEX/ material
  1176. into the output buffer, this function copies it into the token memory
  1177. (in phase two only).
  1178. The abbreviation |app_tok(t)| is used to append token |t| to the current
  1179. token list, and it also makes sure that it is possible to append at least
  1180. one further token without overflow.
  1181. @d app_tok(c) {if (tok_ptr+2>tok_mem_end) overflow("token"); *(tok_ptr++)=c;}
  1182. @<Predec...@>=
  1183. int copy_comment();
  1184. int copy_comment(is_long_comment,bal) /* copies \TEX/ code in comments */
  1185. boolean is_long_comment; /* is this a traditional \CEE/ comment? */
  1186. int bal; /* brace balance */
  1187.   char c; /* current character being copied */
  1188.   while (1) {
  1189.     if (loc>limit) {
  1190.       if (is_long_comment) {
  1191.         if (get_line()==0) {
  1192.           err_print("! Input ended in mid-comment");
  1193. @.Input ended in mid-comment@>
  1194.           loc=buffer+1; goto done;
  1195.         }
  1196.       }
  1197.       else {
  1198.         if (bal>1) err_print("! Missing } in comment");
  1199. @.Missing \} in comment@>
  1200.         goto done;
  1201.       }
  1202.     }
  1203.     c=*(loc++);
  1204.     if (c=='|') return(bal);
  1205.     if (is_long_comment) @<Check for end of comment@>;
  1206.     if (phase==2) {
  1207.       if (ishigh(c)) app_tok(quoted_char);
  1208.       app_tok(c);
  1209.     }
  1210.     @<Copy special things when |c=='@@', '\\'|@>;
  1211.     if (c=='{') bal++;
  1212.     else if (c=='}') {
  1213.       if(bal>1) bal--;
  1214.       else {err_print("! Extra } in comment");
  1215. @.Extra \} in comment@>
  1216.         if (phase==2) tok_ptr--;
  1217.       }
  1218.     }
  1219. done:@<Clear |bal| and |return|@>;
  1220. @ @<Check for end of comment@>=
  1221. if (c=='*' && *loc=='/') {
  1222.   loc++;
  1223.   if (bal>1) err_print("! Missing } in comment");
  1224. @.Missing \} in comment@>
  1225.   goto done;
  1226. @ @<Copy special things when |c=='@@'...@>=
  1227. if (c=='@@') {
  1228.   if (*(loc++)!='@@') {
  1229.     err_print("! Illegal use of @@ in comment");
  1230. @.Illegal use of @@...@>
  1231.     loc-=2; if (phase==2) *(tok_ptr-1)=' '; goto done;
  1232. else if (c=='\\' && *loc!='@@')
  1233.   if (phase==2) app_tok(*(loc++)) else loc++;
  1234. @ We output
  1235. enough right braces to keep \TEX/ happy.
  1236. @<Clear |bal|...@>=
  1237. if (phase==2) while (bal-- >0) app_tok('}');
  1238. return(0);
  1239. @** Parsing.
  1240. The most intricate part of \.{CWEAVE} is its mechanism for converting
  1241. \CEE/-like code into \TEX/ code, and we might as well plunge into this
  1242. aspect of the program now. A ``bottom up'' approach is used to parse the
  1243. \CEE/-like material, since \.{CWEAVE} must deal with fragmentary
  1244. constructions whose overall ``part of speech'' is not known.
  1245. At the lowest level, the input is represented as a sequence of entities
  1246. that we shall call {\it scraps}, where each scrap of information consists
  1247. of two parts, its {\it category} and its {\it translation}. The category
  1248. is essentially a syntactic class, and the translation is a token list that
  1249. represents \TEX/ code. Rules of syntax and semantics tell us how to
  1250. combine adjacent scraps into larger ones, and if we are lucky an entire
  1251. \CEE/ text that starts out as hundreds of small scraps will join
  1252. together into one gigantic scrap whose translation is the desired \TEX/
  1253. code. If we are unlucky, we will be left with several scraps that don't
  1254. combine; their translations will simply be output, one by one.
  1255. The combination rules are given as context-sensitive productions that are
  1256. applied from left to right. Suppose that we are currently working on the
  1257. sequence of scraps $s_1\,s_2\ldots s_n$. We try first to find the longest
  1258. production that applies to an initial substring $s_1\,s_2\ldots\,$; but if
  1259. no such productions exist, we find to find the longest production
  1260. applicable to the next substring $s_2\,s_3\ldots\,$; and if that fails, we
  1261. try to match $s_3\,s_4\ldots\,$, etc.
  1262. A production applies if the category codes have a given pattern. For
  1263. example, one of the productions (see rule~3) is
  1264. $$\hbox{|exp| }\left\{\matrix{\hbox{|binop|}\cr\hbox{|unorbinop|}}\right\}
  1265. \hbox{ |exp| }\RA\hbox{ |exp|}$$
  1266. and it means that three consecutive scraps whose respective categories are
  1267. |exp|, |binop| (or |unorbinop|),
  1268. and |exp| are converted to one scrap whose category
  1269. is |exp|.  The translations of the original
  1270. scraps are simply concatenated.  The case of
  1271. $$\hbox{|exp| |comma| |exp| $\RA$ |exp|} \hskip4emE_1C\,\\{opt}9\,E_2$$
  1272. (rule 4) is only slightly more complicated:
  1273. Here the resulting |exp| translation
  1274. consists not only of the three original translations, but also of the
  1275. tokens |opt| and 9 between the translations of the
  1276. |comma| and the following |exp|.
  1277. In the \TEX/ file, this will specify an optional line break after the
  1278. comma, with penalty 90.
  1279. At each opportunity the longest possible production is applied.  For
  1280. example, if the current sequence of scraps is |int_like| |cast|
  1281. |lbrace|, rule 31 is applied; but if the sequence is |int_like| |cast|
  1282. followed by anything other than |lbrace|, rule 32 takes effect.
  1283. Translation rules such as `$E_1C\,\\{opt}9\,E_2$' above use subscripts
  1284. to distinguish between translations of scraps whose categories have the
  1285. same initial letter; these subscripts are assigned from left to right.
  1286. @ Here is a list of the category codes that scraps can have.
  1287. (A few others, like |int_like|, have already been defined; the
  1288. |cat_name| array contains a complete list.)
  1289. @d exp 1 /* denotes an expression, including perhaps a single identifier */
  1290. @d unop 2 /* denotes a unary operator */
  1291. @d binop 3 /* denotes a binary operator */
  1292. @d unorbinop 4
  1293.   /* denotes an operator that can be unary or binary, depending on context */
  1294. @d cast 5 /* denotes a cast */
  1295. @d question 6 /* denotes a question mark and possibly the expressions flanking it */
  1296. @d lbrace 7 /* denotes a left brace */
  1297. @d rbrace 8 /* denotes a right brace */
  1298. @d decl_head 9 /* denotes an incomplete declaration */
  1299. @d comma 10 /* denotes a comma */
  1300. @d lpar 11 /* denotes a left parenthesis or left bracket */
  1301. @d rpar 12 /* denotes a right parenthesis or right bracket */
  1302. @d prelangle 13 /* denotes `$<$' before we know what it is */
  1303. @d prerangle 14 /* denotes `$>$' before we know what it is */
  1304. @d langle 15 /* denotes `$<$' when it's used as angle bracket in a template */
  1305. @d colcol 18 /* denotes `::' */
  1306. @d base 19 /* denotes a colon that introduces a base specifier */
  1307. @d decl 20 /* denotes a complete declaration */
  1308. @d struct_head 21 /* denotes the beginning of a structure specifier */
  1309. @d stmt 23 /* denotes a complete statement */
  1310. @d function 24 /* denotes a complete function */
  1311. @d fn_decl 25 /* denotes a function declarator */
  1312. @d semi 27 /* denotes a semicolon */
  1313. @d colon 28 /* denotes a colon */
  1314. @d tag 29 /* denotes a statement label */
  1315. @d if_head 30 /* denotes the beginning of a compound conditional */
  1316. @d else_head 31 /* denotes a prefix for a compound statement */
  1317. @d if_clause 32 /* pending \.{if} together with a condition */
  1318. @d lproc 35 /* begins a preprocessor command */
  1319. @d rproc 36 /* ends a preprocessor command */
  1320. @d insert 37 /* a scrap that gets combined with its neighbor */
  1321. @d section_scrap 38 /* section name */
  1322. @d dead 39 /* scrap that won't combine */
  1323. @d begin_arg 58 /* \.{@@[} */
  1324. @d end_arg 59 /* \.{@@]} */
  1325. @<Glo...@>=
  1326. char cat_name[256][12];
  1327. eight_bits cat_index;
  1328. @ @<Set in...@>=
  1329.     for (cat_index=0;cat_index<255;cat_index++)
  1330.       strcpy(cat_name[cat_index],"UNKNOWN");
  1331.     strcpy(cat_name[exp],"exp");
  1332.     strcpy(cat_name[unop],"unop");
  1333.     strcpy(cat_name[binop],"binop");
  1334.     strcpy(cat_name[unorbinop],"unorbinop");
  1335.     strcpy(cat_name[cast],"cast");
  1336.     strcpy(cat_name[question],"?");
  1337.     strcpy(cat_name[lbrace],"{"@q}@>);
  1338.     strcpy(cat_name[rbrace],@q{@>"}");
  1339.     strcpy(cat_name[decl_head],"decl_head");
  1340.     strcpy(cat_name[comma],",");
  1341.     strcpy(cat_name[lpar],"(");
  1342.     strcpy(cat_name[rpar],")");
  1343.     strcpy(cat_name[prelangle],"<");
  1344.     strcpy(cat_name[prerangle],">");
  1345.     strcpy(cat_name[langle],"\\<");
  1346.     strcpy(cat_name[colcol],"::");
  1347.     strcpy(cat_name[base],"\\:");
  1348.     strcpy(cat_name[decl],"decl");
  1349.     strcpy(cat_name[struct_head],"struct_head");
  1350.     strcpy(cat_name[stmt],"stmt");
  1351.     strcpy(cat_name[function],"function");
  1352.     strcpy(cat_name[fn_decl],"fn_decl");
  1353.     strcpy(cat_name[else_like],"else_like");
  1354.     strcpy(cat_name[semi],";");
  1355.     strcpy(cat_name[colon],":");
  1356.     strcpy(cat_name[tag],"tag");
  1357.     strcpy(cat_name[if_head],"if_head");
  1358.     strcpy(cat_name[else_head],"else_head");
  1359.     strcpy(cat_name[if_clause],"if()");
  1360.     strcpy(cat_name[lproc],"#{"@q}@>);
  1361.     strcpy(cat_name[rproc],@q{@>"#}");
  1362.     strcpy(cat_name[insert],"insert");
  1363.     strcpy(cat_name[section_scrap],"section");
  1364.     strcpy(cat_name[dead],"@@d");
  1365.     strcpy(cat_name[public_like],"public");
  1366.     strcpy(cat_name[operator_like],"operator");
  1367.     strcpy(cat_name[new_like],"new");
  1368.     strcpy(cat_name[catch_like],"catch");
  1369.     strcpy(cat_name[for_like],"for");
  1370.     strcpy(cat_name[do_like],"do");
  1371.     strcpy(cat_name[if_like],"if");
  1372.     strcpy(cat_name[raw_rpar],")?");
  1373.     strcpy(cat_name[raw_unorbin],"unorbinop?");
  1374.     strcpy(cat_name[const_like],"const");
  1375.     strcpy(cat_name[raw_int],"raw");
  1376.     strcpy(cat_name[int_like],"int");
  1377.     strcpy(cat_name[case_like],"case");
  1378.     strcpy(cat_name[sizeof_like],"sizeof");
  1379.     strcpy(cat_name[struct_like],"struct");
  1380.     strcpy(cat_name[typedef_like],"typedef");
  1381.     strcpy(cat_name[define_like],"define");
  1382.     strcpy(cat_name[begin_arg],"@@["@q]@>);
  1383.     strcpy(cat_name[end_arg],@q[@>"@@]");
  1384.     strcpy(cat_name[0],"zero");
  1385. @ This code allows \.{CWEAVE} to display its parsing steps.
  1386. print_cat(c) /* symbolic printout of a category */
  1387. eight_bits c;
  1388.   printf(cat_name[c]);
  1389. @ The token lists for translated \TEX/ output contain some special control
  1390. symbols as well as ordinary characters. These control symbols are
  1391. interpreted by \.{CWEAVE} before they are written to the output file.
  1392. \yskip\hang |break_space| denotes an optional line break or an en space;
  1393. \yskip\hang |force| denotes a line break;
  1394. \yskip\hang |big_force| denotes a line break with additional vertical space;
  1395. \yskip\hang |preproc_line| denotes that the line will be printed flush left;
  1396. \yskip\hang |opt| denotes an optional line break (with the continuation
  1397. line indented two ems with respect to the normal starting position)---this
  1398. code is followed by an integer |n|, and the break will occur with penalty
  1399. $10n$;
  1400. \yskip\hang |backup| denotes a backspace of one em;
  1401. \yskip\hang |cancel| obliterates any |break_space|, |opt|, |force|, or
  1402. |big_force| tokens that immediately precede or follow it and also cancels any
  1403. |backup| tokens that follow it;
  1404. \yskip\hang |indent| causes future lines to be indented one more em;
  1405. \yskip\hang |outdent| causes future lines to be indented one less em.
  1406. \yskip\noindent All of these tokens are removed from the \TEX/ output that
  1407. comes from \CEE/ text between \pb\ signs; |break_space| and |force| and
  1408. |big_force| become single spaces in this mode. The translation of other
  1409. \CEE/ texts results in \TEX/ control sequences \.{\\1}, \.{\\2},
  1410. \.{\\3}, \.{\\4}, \.{\\5}, \.{\\6}, \.{\\7}, \.{\\8}
  1411. corresponding respectively to
  1412. |indent|, |outdent|, |opt|, |backup|, |break_space|, |force|,
  1413. |big_force| and |preproc_line|.
  1414. However, a sequence of consecutive `\.\ ', |break_space|,
  1415. |force|, and/or |big_force| tokens is first replaced by a single token
  1416. (the maximum of the given ones).
  1417. The token |math_rel| will be translated into
  1418. \.{\\MRL\{}, and it will get a matching \.\} later.
  1419. Other control sequences in the \TEX/ output will be
  1420. `\.{\\\\\{}$\,\ldots\,$\.\}'
  1421. surrounding identifiers, `\.{\\\&\{}$\,\ldots\,$\.\}' surrounding
  1422. reserved words, `\.{\\.\{}$\,\ldots\,$\.\}' surrounding strings,
  1423. `\.{\\C\{}$\,\ldots\,$\.\}$\,$|force|' surrounding comments, and
  1424. `\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding section names, where
  1425. |n| is the section number.
  1426. @d math_rel 0206
  1427. @d big_cancel 0210 /* like |cancel|, also overrides spaces */
  1428. @d cancel 0211 /* overrides |backup|, |break_space|, |force|, |big_force| */
  1429. @d indent 0212 /* one more tab (\.{\\1}) */
  1430. @d outdent 0213 /* one less tab (\.{\\2}) */
  1431. @d opt 0214 /* optional break in mid-statement (\.{\\3}) */
  1432. @d backup 0215 /* stick out one unit to the left (\.{\\4}) */
  1433. @d break_space 0216 /* optional break between statements (\.{\\5}) */
  1434. @d force 0217 /* forced break between statements (\.{\\6}) */
  1435. @d big_force 0220 /* forced break with additional space (\.{\\7}) */
  1436. @d preproc_line 0221 /* begin line without indentation (\.{\\8}) */
  1437. @^high-bit character handling@>
  1438. @d quoted_char 0222
  1439.         /* introduces a character token in the range |0200|--|0377| */
  1440. @d end_translation 0223 /* special sentinel token at end of list */
  1441. @d inserted 0224 /* sentinel to mark translations of inserts */
  1442. @ The raw input is converted into scraps according to the following table,
  1443. which gives category codes followed by the translations.
  1444. \def\stars {\.{**}}%
  1445. The symbol `\stars' stands for `\.{\\\&\{{\rm identifier}\}}',
  1446. i.e., the identifier itself treated as a reserved word.
  1447. The right-hand column is the so-called |mathness|, which is explained
  1448. further below.
  1449. An identifier |c| of length 1 is translated as \.{\\\v c} instead of
  1450. as \.{\\\\\{c\}}. An identifier \.{CAPS} in all caps is translated as
  1451. \.{\\.\{CAPS\}} instead of as \.{\\\\\{CAPS\}}. An identifier that has
  1452. become a reserved word via |typedef| is translated with \.{\\\&} replacing
  1453. \.{\\\\} and |raw_int| replacing |exp|.
  1454. A string of length greater than 20 is broken into pieces of size at most~20
  1455. with discretionary breaks in between.
  1456. \yskip\halign{\quad#\hfil&\quad#\hfil&\quad\hfil#\hfil\cr
  1457. \.{!=}&|binop|: \.{\\I}&yes\cr
  1458. \.{<=}&|binop|: \.{\\Z}&yes\cr
  1459. \.{>=}&|binop|: \.{\\G}&yes\cr
  1460. \.{==}&|binop|: \.{\\E}&yes\cr
  1461. \.{\&\&}&|binop|: \.{\\W}&yes\cr
  1462. \.{\v\v}&|binop|: \.{\\V}&yes\cr
  1463. \.{++}&|binop|: \.{\\PP}&yes\cr
  1464. \.{--}&|binop|: \.{\\MM}&yes\cr
  1465. \.{->}&|binop|: \.{\\MG}&yes\cr
  1466. \.{>>}&|binop|: \.{\\GG}&yes\cr
  1467. \.{<<}&|binop|: \.{\\LL}&yes\cr
  1468. \.{::}&|colcol|: \.{\\DC}&maybe\cr
  1469. \.{.*}&|binop|: \.{\\PA}&yes\cr
  1470. \.{->*}&|binop|: \.{\\MGA}&yes\cr
  1471. \.{...}&|exp|: \.{\\,\\ldots\\,}&yes\cr
  1472. \."string\."&|exp|: \.{\\.\{}string with special characters quoted\.\}&maybe\cr
  1473. \.{@@=}string\.{@@>}&|exp|: \.{\\vb\{}string with special characters
  1474.   quoted\.\}&maybe\cr
  1475. \.{@@'7'}&|exp|: \.{\\.\{@@'7'\}}&maybe\cr
  1476. \.{077} or \.{\\77}&|exp|: \.{\\T\{\\\~77\}}&maybe\cr
  1477. \.{0x7f}&|exp|: \.{\\T\{\\\^7f\}}&maybe\cr
  1478. \.{77}&|exp|: \.{\\T\{77\}}&maybe\cr
  1479. \.{77L}&|exp|: \.{\\T\{77\\\$L\}}&maybe\cr
  1480. \.{0.1E5}&|exp|: \.{\\T\{0.1\\\_5\}}&maybe\cr
  1481. \.+&|unorbinop|: \.+&yes\cr
  1482. \.-&|unorbinop|: \.-&yes\cr
  1483. \.*&|raw_unorbin|: \.*&yes\cr
  1484. \./&|binop|: \./&yes\cr
  1485. \.<&|binop|: \.<&yes\cr
  1486. \.=&|binop|: \.{\\K}&yes\cr
  1487. \.>&|binop|: \.>&yes\cr
  1488. \..&|binop|: \..&yes\cr
  1489. \.{\v}&|binop|: \.{\\OR}&yes\cr
  1490. \.\^&|binop|: \.{\\XOR}&yes\cr
  1491. \.\%&|binop|: \.{\\MOD}&yes\cr
  1492. \.?&|question|: \.{\\?}&yes\cr
  1493. \.!&|unop|: \.{\\R}&yes\cr
  1494. \.\~&|unop|: \.{\\CM}&yes\cr
  1495. \.\&&|raw_unorbin|: \.{\\AND}&yes\cr
  1496. \.(&|lpar|: \.(&maybe\cr
  1497. \.[&|lpar|: \.[&maybe\cr
  1498. \.)&|raw_rpar|: \.)&maybe\cr
  1499. \.]&|raw_rpar|: \.]&maybe\cr
  1500. \.\{&|lbrace|: \.\{&yes\cr
  1501. \.\}&|lbrace|: \.\}&yes\cr
  1502. \.,&|comma|: \.,&yes\cr
  1503. \.;&|semi|: \.;&maybe\cr
  1504. \.:&|colon|: \.:&maybe\cr
  1505. \.\# (within line)&|unorbinop|: \.{\\\#}&yes\cr
  1506. \.\# (at beginning)&|lproc|:  |force| |preproc_line| \.{\\\#}&no\cr
  1507. end of \.\# line&|rproc|:  |force|&no\cr
  1508. identifier&|exp|: \.{\\\\\{}identifier with underlines quoted\.\}&maybe\cr
  1509. \.{asm}&|sizeof_like|: \stars&maybe\cr
  1510. \.{auto}&|int_like|: \stars&maybe\cr
  1511. \.{break}&|case_like|: \stars&maybe\cr
  1512. \.{case}&|case_like|: \stars&maybe\cr
  1513. \.{catch}&|catch_like|: \stars&maybe\cr
  1514. \.{char}&|raw_int|: \stars&maybe\cr
  1515. \.{class}&|struct_like|: \stars&maybe\cr
  1516. \.{clock\_t}&|raw_int|: \stars&maybe\cr
  1517. \.{const}&|const_like|: \stars&maybe\cr
  1518. \.{continue}&|case_like|: \stars&maybe\cr
  1519. \.{default}&|case_like|: \stars&maybe\cr
  1520. \.{define}&|define_like|: \stars&maybe\cr
  1521. \.{defined}&|sizeof_like|: \stars&maybe\cr
  1522. \.{delete}&|sizeof_like|: \stars&maybe\cr
  1523. \.{div\_t}&|raw_int|: \stars&maybe\cr
  1524. \.{do}&|do_like|: \stars&maybe\cr
  1525. \.{double}&|raw_int|: \stars&maybe\cr
  1526. \.{elif}&|if_like|: \stars&maybe\cr
  1527. \.{else}&|else_like|: \stars&maybe\cr
  1528. \.{endif}&|if_like|: \stars&maybe\cr
  1529. \.{enum}&|struct_like|: \stars&maybe\cr
  1530. \.{error}&|if_like|: \stars&maybe\cr
  1531. \.{extern}&|int_like|: \stars&maybe\cr
  1532. \.{FILE}&|raw_int|: \stars&maybe\cr
  1533. \.{float}&|raw_int|: \stars&maybe\cr
  1534. \.{for}&|for_like|: \stars&maybe\cr
  1535. \.{fpos\_t}&|raw_int|: \stars&maybe\cr
  1536. \.{friend}&|int_like|: \stars&maybe\cr
  1537. \.{goto}&|case_like|: \stars&maybe\cr
  1538. \.{if}&|if_like|: \stars&maybe\cr
  1539. \.{ifdef}&|if_like|: \stars&maybe\cr
  1540. \.{ifndef}&|if_like|: \stars&maybe\cr
  1541. \.{include}&|if_like|: \stars&maybe\cr
  1542. \.{inline}&|int_like|: \stars&maybe\cr
  1543. \.{int}&|raw_int|: \stars&maybe\cr
  1544. \.{jmp\_buf}&|raw_int|: \stars&maybe\cr
  1545. \.{ldiv\_t}&|raw_int|: \stars&maybe\cr
  1546. \.{line}&|if_like|: \stars&maybe\cr
  1547. \.{long}&|raw_int|: \stars&maybe\cr
  1548. \.{new}&|new_like|: \stars&maybe\cr
  1549. \.{NULL}&|exp|: \.{\\NULL}&yes\cr
  1550. \.{offsetof}&|sizeof_like|: \stars&maybe\cr
  1551. \.{operator}&|operator_like|: \stars&maybe\cr
  1552. \.{pragma}&|if_like|: \stars&maybe\cr
  1553. \.{private}&|public_like|: \stars&maybe\cr
  1554. \.{protected}&|public_like|: \stars&maybe\cr
  1555. \.{ptrdiff\_t}&|raw_int|: \stars&maybe\cr
  1556. \.{public}&|public_like|: \stars&maybe\cr
  1557. \.{register}&|int_like|: \stars&maybe\cr
  1558. \.{return}&|case_like|: \stars&maybe\cr
  1559. \.{short}&|raw_int|: \stars&maybe\cr
  1560. \.{sig\_atomic\_t}&|raw_int|: \stars&maybe\cr
  1561. \.{signed}&|raw_int|: \stars&maybe\cr
  1562. \.{size\_t}&|raw_int|: \stars&maybe\cr
  1563. \.{sizeof}&|sizeof_like|: \stars&maybe\cr
  1564. \.{static}&|int_like|: \stars&maybe\cr
  1565. \.{struct}&|struct_like|: \stars&maybe\cr
  1566. \.{switch}&|if_like|: \stars&maybe\cr
  1567. \.{template}&|int_like|: \stars&maybe\cr
  1568. \.{TeX}&|exp|: \.{\\TeX}&yes\cr
  1569. \.{this}&|exp|: \.{\\this}&yes\cr
  1570. \.{throw}&|case_like|: \stars&maybe\cr
  1571. \.{time\_t}&|raw_int|: \stars&maybe\cr
  1572. \.{try}&|else_like|: \stars&maybe\cr
  1573. \.{typedef}&|typedef_like|: \stars&maybe\cr
  1574. \.{undef}&|if_like|: \stars&maybe\cr
  1575. \.{union}&|struct_like|: \stars&maybe\cr
  1576. \.{unsigned}&|raw_int|: \stars&maybe\cr
  1577. \.{va\_dcl}&|decl|: \stars&maybe\cr
  1578. \.{va\_list}&|raw_int|: \stars&maybe\cr
  1579. \.{virtual}&|int_like|: \stars&maybe\cr
  1580. \.{void}&|raw_int|: \stars&maybe\cr
  1581. \.{volatile}&|const_like|: \stars&maybe\cr
  1582. \.{wchar\_t}&|raw_int|: \stars&maybe\cr
  1583. \.{while}&|if_like|: \stars&maybe\cr
  1584. \.{@@,}&|insert|: \.{\\,}&maybe\cr
  1585. \.{@@\v}&|insert|:  |opt| \.0&maybe\cr
  1586. \.{@@/}&|insert|:  |force|&no\cr
  1587. \.{@@\#}&|insert|:  |big_force|&no\cr
  1588. \.{@@+}&|insert|:  |big_cancel| \.{\{\}} |break_space|
  1589.   \.{\{\}} |big_cancel|&no\cr
  1590. \.{@@;}&|semi|: &maybe\cr
  1591. \.{@@[@q]@>}&|begin_arg|: &maybe\cr
  1592. \.{@q[@>@@]}&|end_arg|: &maybe\cr
  1593. \.{@@\&}&|insert|: \.{\\J}&maybe\cr
  1594. \.{@@h}&|insert|: |force| \.{\\ATH} |force|&no\cr
  1595. \.{@@<}\thinspace section name\thinspace\.{@@>}&|section_scrap|:
  1596.  \.{\\X}$n$\.:translated section name\.{\\X}&maybe\cr
  1597. \.{@@(@q)@>}\thinspace section name\thinspace\.{@@>}&|section_scrap|:
  1598.  \.{\\X}$n$\.{:\\.\{}section name with special characters
  1599.       quoted\.{\ \}\\X}&maybe\cr
  1600. \.{/*}comment\.{*/}&|insert|: |cancel|
  1601.       \.{\\C\{}translated comment\.\} |force|&no\cr
  1602. \.{//}comment&|insert|: |cancel|
  1603.       \.{\\SHC\{}translated comment\.\} |force|&no\cr
  1604. The construction \.{@@t}\thinspace stuff\/\thinspace\.{@@>} contributes
  1605. \.{\\hbox\{}\thinspace  stuff\/\thinspace\.\} to the following scrap.
  1606. @i prod.w
  1607. @* Implementing the productions.
  1608. More specifically, a scrap is a structure consisting of a category
  1609. |cat| and a |text_pointer| |trans|, which points to the translation in
  1610. |tok_start|.  When \CEE/ text is to be processed with the grammar above,
  1611. we form an array |scrap_info| containing the initial scraps.
  1612. Our production rules have the nice property that the right-hand side is never
  1613. longer than the left-hand side. Therefore it is convenient to use sequential
  1614. allocation for the current sequence of scraps. Five pointers are used to
  1615. manage the parsing:
  1616. \yskip\hang |pp| is a pointer into |scrap_info|.  We will try to match
  1617. the category codes |pp->cat,@,@,(pp+1)->cat|$,\,\,\ldots\,$
  1618. to the left-hand sides of productions.
  1619. \yskip\hang |scrap_base|, |lo_ptr|, |hi_ptr|, and |scrap_ptr| are such that
  1620. the current sequence of scraps appears in positions |scrap_base| through
  1621. |lo_ptr| and |hi_ptr| through |scrap_ptr|, inclusive, in the |cat| and
  1622. |trans| arrays. Scraps located between |scrap_base| and |lo_ptr| have
  1623. been examined, while those in positions |>=hi_ptr| have not yet been
  1624. looked at by the parsing process.
  1625. \yskip\noindent Initially |scrap_ptr| is set to the position of the final
  1626. scrap to be parsed, and it doesn't change its value. The parsing process
  1627. makes sure that |lo_ptr>=pp+3|, since productions have as many as four terms,
  1628. by moving scraps from |hi_ptr| to |lo_ptr|. If there are
  1629. fewer than |pp+3| scraps left, the positions up to |pp+3| are filled with
  1630. blanks that will not match in any productions. Parsing stops when
  1631. |pp==lo_ptr+1| and |hi_ptr==scrap_ptr+1|.
  1632. Since the |scrap| structure will later be used for other purposes, we
  1633. declare its second element as unions.
  1634. @<Type...@>=
  1635. typedef struct {
  1636.   eight_bits cat;
  1637.   eight_bits mathness;
  1638.   union {
  1639.     text_pointer Trans;
  1640.     @<Rest of |trans_plus| union@>@;
  1641.   } trans_plus;
  1642. } scrap;
  1643. typedef scrap *scrap_pointer;
  1644. @ @d trans trans_plus.Trans /* translation texts of scraps */
  1645. @<Global...@>=
  1646. scrap scrap_info[max_scraps]; /* memory array for scraps */
  1647. scrap_pointer scrap_info_end=scrap_info+max_scraps -1; /* end of |scrap_info| */
  1648. scrap_pointer pp; /* current position for reducing productions */
  1649. scrap_pointer scrap_base; /* beginning of the current scrap sequence */
  1650. scrap_pointer scrap_ptr; /* ending of the current scrap sequence */
  1651. scrap_pointer lo_ptr; /* last scrap that has been examined */
  1652. scrap_pointer hi_ptr; /* first scrap that has not been examined */
  1653. scrap_pointer max_scr_ptr; /* largest value assumed by |scrap_ptr| */
  1654. @ @<Set init...@>=
  1655. scrap_base=scrap_info+1;
  1656. max_scr_ptr=scrap_ptr=scrap_info;
  1657. @ Token lists in |@!tok_mem| are composed of the following kinds of
  1658. items for \TEX/ output.
  1659. \yskip\item{$\bullet$}Character codes and special codes like |force| and
  1660. |math_rel| represent themselves;
  1661. \item{$\bullet$}|id_flag+p| represents \.{\\\\\{{\rm identifier $p$}\}};
  1662. \item{$\bullet$}|res_flag+p| represents \.{\\\&\{{\rm identifier $p$}\}};
  1663. \item{$\bullet$}|section_flag+p| represents section name |p|;
  1664. \item{$\bullet$}|tok_flag+p| represents token list number |p|;
  1665. \item{$\bullet$}|inner_tok_flag+p| represents token list number |p|, to be
  1666. translated without line-break controls.
  1667. @d id_flag 10240 /* signifies an identifier */
  1668. @d res_flag 2*id_flag /* signifies a reserved word */
  1669. @d section_flag 3*id_flag /* signifies a section name */
  1670. @d tok_flag 4*id_flag /* signifies a token list */
  1671. @d inner_tok_flag 5*id_flag /* signifies a token list in `\pb' */
  1672. print_text(p) /* prints a token list for debugging; not used in |main| */
  1673. text_pointer p;
  1674.   token_pointer j; /* index into |tok_mem| */
  1675.   sixteen_bits r; /* remainder of token after the flag has been stripped off */
  1676.   if (p>=text_ptr) printf("BAD");
  1677.   else for (j=*p; j<*(p+1); j++) {
  1678.     r=*j%id_flag;
  1679.     switch (*j/id_flag) {
  1680.       case 1: printf("\\\\{"@q}@>); print_id((name_dir+r)); printf(@q{@>"}");
  1681.         break; /* |id_flag| */
  1682.       case 2: printf("\\&{"@q}@>); print_id((name_dir+r)); printf(@q{@>"}");
  1683.         break; /* |res_flag| */
  1684.       case 3: printf("<"); print_section_name((name_dir+r)); printf(">");
  1685.         break; /* |section_flag| */
  1686.       case 4: printf("[[%d]]",r); break; /* |tok_flag| */
  1687.       case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
  1688.       default: @<Print token |r| in symbolic form@>;
  1689.     }
  1690.   fflush(stdout);
  1691. @ @<Print token |r|...@>=
  1692. switch (r) {
  1693.   case math_rel: printf("\\mathrel{"@q}@>); break;
  1694.   case big_cancel: printf("[ccancel]"); break;
  1695.   case cancel: printf("[cancel]"); break;
  1696.   case indent: printf("[indent]"); break;
  1697.   case outdent: printf("[outdent]"); break;
  1698.   case backup: printf("[backup]"); break;
  1699.   case opt: printf("[opt]"); break;
  1700.   case break_space: printf("[break]"); break;
  1701.   case force: printf("[force]"); break;
  1702.   case big_force: printf("[fforce]"); break;
  1703.   case preproc_line: printf("[preproc]"); break;
  1704.   case quoted_char: j++; printf("[%o]",(unsigned)*j); break;
  1705.   case end_translation: printf("[quit]"); break;
  1706.   case inserted: printf("[inserted]"); break;
  1707.   default: putxchar(r);
  1708. @ The production rules listed above are embedded directly into \.{CWEAVE},
  1709. since it is easier to do this than to write an interpretive system
  1710. that would handle production systems in general. Several macros are defined
  1711. here so that the program for each production is fairly short.
  1712. All of our productions conform to the general notion that some |k|
  1713. consecutive scraps starting at some position |j| are to be replaced by a
  1714. single scrap of some category |c| whose translation is composed from the
  1715. translations of the disappearing scraps. After this production has been
  1716. applied, the production pointer |pp| should change by an amount |d|. Such
  1717. a production can be represented by the quadruple |(j,k,c,d)|. For example,
  1718. the production `|exp@,comma@,exp| $\RA$ |exp|' would be represented by
  1719. `|(pp,3,exp,-2)|'; in this case the pointer |pp| should decrease by 2
  1720. after the production has been applied, because some productions with
  1721. |exp| in their second or third positions might now match,
  1722. but no productions have
  1723. |exp| in the fourth position of their left-hand sides. Note that
  1724. the value of |d| is determined by the whole collection of productions, not
  1725. by an individual one.
  1726. The determination of |d| has been
  1727. done by hand in each case, based on the full set of productions but not on
  1728. the grammar of \CEE/ or on the rules for constructing the initial
  1729. scraps.
  1730. We also attach a serial number to each production, so that additional
  1731. information is available when debugging. For example, the program below
  1732. contains the statement `|reduce(pp,3,exp,-2,4)|' when it implements
  1733. the production just mentioned.
  1734. Before calling |reduce|, the program should have appended the tokens of
  1735. the new translation to the |tok_mem| array. We commonly want to append
  1736. copies of several existing translations, and macros are defined to
  1737. simplify these common cases. For example, \\{app2}|(pp)| will append the
  1738. translations of two consecutive scraps, |pp->trans| and |(pp+1)->trans|, to
  1739. the current token list. If the entire new translation is formed in this
  1740. way, we write `|squash(j,k,c,d,n)|' instead of `|reduce(j,k,c,d,n)|'. For
  1741. example, `|squash(pp,3,exp,-2,3)|' is an abbreviation for `\\{app3}|(pp);
  1742. reduce(pp,3,exp,-2,3)|'.
  1743. A couple more words of explanation:
  1744. Both |big_app| and |app| append a token (while |big_app1| to |big_app4|
  1745. append the specified number of scrap translations) to the current token list.
  1746. The difference between |big_app| and |app| is simply that |big_app|
  1747. checks whether there can be a conflict between math and non-math
  1748. tokens, and intercalates a `\.{\$}' token if necessary.  When in
  1749. doubt what to use, use |big_app|.
  1750. The |mathness| is an attribute of scraps that says whether they are
  1751. to be printed in a math mode context or not.  It is separate from the
  1752. ``part of speech'' (the |cat|) because to make each |cat| have
  1753. a fixed |mathness| (as in the original \.{WEAVE}) would multiply the
  1754. number of necessary production rules.
  1755. The low two bits (i.e. |mathness % 4|) control the left boundary.
  1756. (We need two bits because we allow cases |yes_math|, |no_math| and
  1757. |maybe_math|, which can go either way.)
  1758. The next two bits (i.e. |mathness / 4|) control the right boundary.
  1759. If we combine two scraps and the right boundary of the first has
  1760. a different mathness from the left boundary of the second, we
  1761. insert a \.{\$} in between.  Similarly, if at printing time some
  1762. irreducible scrap has a |yes_math| boundary the scrap gets preceded
  1763. or followed by a \.{\$}. The left boundary is |maybe_math| if and
  1764. only if the right boundary is.
  1765. The code below is an exact translation of the production rules into
  1766. \CEE/, using such macros, and the reader should have no difficulty
  1767. understanding the format by comparing the code with the symbolic
  1768. productions as they were listed earlier.
  1769. @d no_math 2 /* should be in horizontal mode */
  1770. @d yes_math 1 /* should be in math mode */
  1771. @d maybe_math 0 /* works in either horizontal or math mode */
  1772. @d big_app2(a) big_app1(a);big_app1(a+1)
  1773. @d big_app3(a) big_app2(a);big_app1(a+2)
  1774. @d big_app4(a) big_app3(a);big_app1(a+3)
  1775. @d app(a) *(tok_ptr++)=a
  1776. @d app1(a) *(tok_ptr++)=tok_flag+(int)((a)->trans-tok_start)
  1777. @<Global...@>=
  1778. int cur_mathness, init_mathness;
  1779. app_str(s)
  1780. char *s;
  1781.   while (*s) app_tok(*(s++));
  1782. big_app(a)
  1783. token a;
  1784.         if (a==' ' || (a>=big_cancel && a<=big_force)) /* non-math token */ {
  1785.                 if (cur_mathness==maybe_math) init_mathness=no_math;
  1786.                 else if (cur_mathness==yes_math) app_str("{}$");
  1787.                 cur_mathness=no_math;
  1788.         }
  1789.         else {
  1790.                 if (cur_mathness==maybe_math) init_mathness=yes_math;
  1791.                 else if (cur_mathness==no_math) app_str("${}");
  1792.                 cur_mathness=yes_math;
  1793.         }
  1794.         app(a);
  1795. big_app1(a)
  1796. scrap_pointer a;
  1797.   switch (a->mathness % 4) { /* left boundary */
  1798.   case (no_math):
  1799.     if (cur_mathness==maybe_math) init_mathness=no_math;
  1800.     else if (cur_mathness==yes_math) app_str("{}$");
  1801.     cur_mathness=a->mathness / 4; /* right boundary */
  1802.     break;
  1803.   case (yes_math):
  1804.     if (cur_mathness==maybe_math) init_mathness=yes_math;
  1805.     else if (cur_mathness==no_math) app_str("${}");
  1806.     cur_mathness=a->mathness / 4; /* right boundary */
  1807.     break;
  1808.   case (maybe_math): /* no changes */ break;
  1809.   app(tok_flag+(int)((a)->trans-tok_start));
  1810. @ Let us consider the big switch for productions now, before looking
  1811. at its context. We want to design the program so that this switch
  1812. works, so we might as well not keep ourselves in suspense about exactly what
  1813. code needs to be provided with a proper environment.
  1814. @d cat1 (pp+1)->cat
  1815. @d cat2 (pp+2)->cat
  1816. @d cat3 (pp+3)->cat
  1817. @d lhs_not_simple (pp->cat!=semi && pp->cat!=raw_int && pp->cat!=raw_unorbin
  1818.             && pp->cat!=raw_rpar && pp->cat!=const_like)
  1819. @<Match a production at |pp|, or increase |pp| if there is no match@>= {
  1820.   if (cat1==end_arg && lhs_not_simple)
  1821.     if (pp->cat==begin_arg) squash(pp,2,exp,-2,110);
  1822.     else squash(pp,2,end_arg,-1,111);
  1823.   else if (cat1==insert) squash(pp,2,pp->cat,-2,0);
  1824.   else if (cat2==insert) squash(pp+1,2,(pp+1)->cat,-1,0);
  1825.   else if (cat3==insert) squash(pp+2,2,(pp+2)->cat,0,0);
  1826.   else
  1827.   switch (pp->cat) {
  1828.     case exp: @<Cases for |exp|@>; @+break;
  1829.     case lpar: @<Cases for |lpar|@>; @+break;
  1830.     case question: @<Cases for |question|@>; @+break;
  1831.     case unop: @<Cases for |unop|@>; @+break;
  1832.     case unorbinop: @<Cases for |unorbinop|@>; @+break;
  1833.     case binop: @<Cases for |binop|@>; @+break;
  1834.     case cast: @<Cases for |cast|@>; @+break;
  1835.     case sizeof_like: @<Cases for |sizeof_like|@>; @+break;
  1836.     case int_like: @<Cases for |int_like|@>; @+break;
  1837.     case decl_head: @<Cases for |decl_head|@>; @+break;
  1838.     case decl: @<Cases for |decl|@>; @+break;
  1839.     case typedef_like: @<Cases for |typedef_like|@>; @+break;
  1840.     case struct_like: @<Cases for |struct_like|@>; @+break;
  1841.     case struct_head: @<Cases for |struct_head|@>; @+break;
  1842.     case fn_decl: @<Cases for |fn_decl|@>; @+break;
  1843.     case function: @<Cases for |function|@>; @+break;
  1844.     case lbrace: @<Cases for |lbrace|@>; @+break;
  1845.     case do_like: @<Cases for |do_like|@>; @+break;
  1846.     case if_like: @<Cases for |if_like|@>; @+break;
  1847.     case for_like: @<Cases for |for_like|@>; @+break;
  1848.     case else_like: @<Cases for |else_like|@>; @+break;
  1849.     case if_clause: @<Cases for |if_clause|@>; @+break;
  1850.     case if_head: @<Cases for |if_head|@>; @+break;
  1851.     case else_head: @<Cases for |else_head|@>; @+break;
  1852.     case case_like: @<Cases for |case_like|@>; @+break;
  1853.     case stmt: @<Cases for |stmt|@>; @+break;
  1854.     case tag: @<Cases for |tag|@>; @+break;
  1855.     case semi: @<Cases for |semi|@>; @+break;
  1856.     case lproc: @<Cases for |lproc|@>; @+break;
  1857.     case section_scrap: @<Cases for |section_scrap|@>; @+break;
  1858.     case insert: @<Cases for |insert|@>; @+break;
  1859.     case prelangle: @<Cases for |prelangle|@>; @+break;
  1860.     case prerangle: @<Cases for |prerangle|@>; @+break;
  1861.     case langle: @<Cases for |langle|@>; @+break;
  1862.     case public_like: @<Cases for |public_like|@>; @+break;
  1863.     case colcol: @<Cases for |colcol|@>; @+break;
  1864.     case new_like: @<Cases for |new_like|@>; @+break;
  1865.     case operator_like: @<Cases for |operator_like|@>; @+break;
  1866.     case catch_like: @<Cases for |catch_like|@>; @+break;
  1867.     case base: @<Cases for |base|@>; @+break;
  1868.     case raw_rpar: @<Cases for |raw_rpar|@>; @+break;
  1869.     case raw_unorbin: @<Cases for |raw_unorbin|@>; @+break;
  1870.     case const_like: @<Cases for |const_like|@>; @+break;
  1871.     case raw_int: @<Cases for |raw_int|@>; @+break;
  1872.   pp++; /* if no match was found, we move to the right */
  1873. @ In \CEE/, new specifier names can be defined via |typedef|, and we want
  1874. to make the parser recognize future occurrences of the identifier thus
  1875. defined as specifiers.  This is done by the procedure |make_reserved|,
  1876. which changes the |ilk| of the relevant identifier.
  1877. We first need a procedure to recursively seek the first
  1878. identifier in a token list, because the identifier might
  1879. be enclosed in parentheses, as when one defines a function
  1880. returning a pointer.
  1881. @d no_ident_found 0 /* distinct from any identifier token */
  1882. token_pointer
  1883. find_first_ident(p)
  1884. text_pointer p;
  1885.   token_pointer q; /* token to be returned */
  1886.   token_pointer j; /* token being looked at */
  1887.   sixteen_bits r; /* remainder of token after the flag has been stripped off */
  1888.   if (p>=text_ptr) confusion("find_first_ident");
  1889.   for (j=*p; j<*(p+1); j++) {
  1890.     r=*j%id_flag;
  1891.     switch (*j/id_flag) {
  1892.       case 1: case 2: return j;
  1893.       case 4: case 5: /* |tok_flag| or |inner_tok_flag| */
  1894.         if ((q=find_first_ident(tok_start+r))!=no_ident_found)
  1895.           return q;
  1896.       default: ; /* char, |section_flag|, fall thru: move on to next token */
  1897.         if (*j==inserted) return no_ident_found; /* ignore inserts */
  1898.     }
  1899.   return no_ident_found;
  1900. @ The scraps currently being parsed must be inspected for any
  1901. occurrence of the identifier that we're making reserved; hence
  1902. the |for| loop below.
  1903. make_reserved(p) /* make the first identifier in |p->trans| like |int| */
  1904. scrap_pointer p;
  1905.   sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
  1906.   token_pointer tok_loc; /* pointer to |tok_value| */
  1907.   if ((tok_loc=find_first_ident(p->trans))==no_ident_found)
  1908.     return; /* this should not happen */
  1909.   tok_value=*tok_loc;
  1910.   for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
  1911.     if (p->cat==exp) {
  1912.       if (**(p->trans)==tok_value) {
  1913.         p->cat=raw_int;
  1914.         **(p->trans)=tok_value%id_flag+res_flag;
  1915.       }
  1916.     }
  1917.   (name_dir+(sixteen_bits)(tok_value%id_flag))->ilk=raw_int;
  1918.   *tok_loc=tok_value%id_flag+res_flag;
  1919. @ In the following situations we want to mark the occurrence of
  1920. an identifier as a definition: when |make_reserved| is just about to be
  1921. used; after a specifier, as in |char **argv|;
  1922. before a colon, as in \\{found}:; and in the declaration of a function,
  1923. as in \\{main}()$\{\ldots;\}$.  This is accomplished by the invocation
  1924. of |make_underlined| at appropriate times.  Notice that, in the declaration
  1925. of a function, we only find out that the identifier is being defined after
  1926. it has been swallowed up by an |exp|.
  1927. make_underlined(p)
  1928. /* underline the entry for the first identifier in |p->trans| */
  1929. scrap_pointer p;
  1930.   token_pointer tok_loc; /* where the first identifier appears */
  1931.   if ((tok_loc=find_first_ident(p->trans))==no_ident_found)
  1932.     return; /* this happens after parsing the |()| in |double f();| */
  1933.   xref_switch=def_flag;
  1934.   underline_xref(*tok_loc%id_flag+name_dir);
  1935. @ We cannot use |new_xref| to underline a cross-reference at this point
  1936. because this would just make a new cross-reference at the end of the list.
  1937. We actually have to search through the list for the existing
  1938. cross-reference.
  1939. @<Predecl...@>=
  1940. void  underline_xref();
  1941. underline_xref(p)
  1942. name_pointer p;
  1943.   xref_pointer q=(xref_pointer)p->xref; /* pointer to cross-reference being examined */
  1944.   xref_pointer r; /* temporary pointer for permuting cross-references */
  1945.   sixteen_bits m; /* cross-reference value to be installed */
  1946.   sixteen_bits n; /* cross-reference value being examined */
  1947.   if (no_xref) return;
  1948.   m=section_count+xref_switch;
  1949.   while (q != xmem) {
  1950.     n=q->num;
  1951.     if (n==m) return;
  1952.     else if (m==n+def_flag) {
  1953.         q->num=m; return;
  1954.     }
  1955.     else if (n>=def_flag && n<m) break;
  1956.     q=q->xlink;
  1957.   @<Insert new cross-reference at |q|, not at beginning of list@>;
  1958. @ We get to this section only when the identifier is one letter long,
  1959. so it didn't get a non-underlined entry during phase one.  But it may
  1960. have got some explicitly underlined entries in later sections, so in order
  1961. to preserve the numerical order of the entries in the index, we have
  1962. to insert the new cross-reference not at the beginning of the list
  1963. (namely, at |p->xref|), but rather right before |q|.
  1964. @<Insert new cross-reference at |q|...@>=
  1965.   append_xref(0); /* this number doesn't matter */
  1966.   xref_ptr->xlink=(xref_pointer)p->xref; r=xref_ptr;
  1967.   p->xref=(char*)xref_ptr;
  1968.   while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
  1969.   r->num=m; /* everything from |q| on is left undisturbed */
  1970. @ Now comes the code that tries to match each production starting
  1971. with a particular type of scrap. Whenever a match is discovered,
  1972. the |squash| or |reduce| macro will cause the appropriate action
  1973. to be performed, followed by |goto found|.
  1974. @<Cases for |exp|@>=
  1975. if (cat1==lbrace || cat1==int_like || cat1==decl) {
  1976.   make_underlined(pp); big_app1(pp); big_app(indent); app(indent);
  1977.   reduce(pp,1,fn_decl,0,1);
  1978. else if (cat1==unop) squash(pp,2,exp,-2,2);
  1979. else if ((cat1==binop || cat1==unorbinop) && cat2==exp)
  1980.         squash(pp,3,exp,-2,3);
  1981. else if (cat1==comma && cat2==exp) {
  1982.   big_app2(pp);
  1983.   app(opt); app('9'); big_app1(pp+2); reduce(pp,3,exp,-2,4);
  1984. else if (cat1==exp || cat1==cast) squash(pp,2,exp,-2,5);
  1985. else if (cat1==semi) squash(pp,2,stmt,-1,6);
  1986. else if (cat1==colon) {
  1987.   make_underlined (pp);  squash(pp,2,tag,0,7);
  1988. else if (cat1==base) {
  1989.   if (cat2==int_like && cat3==comma) {
  1990.     big_app1(pp+1); big_app(' '); big_app2(pp+2);
  1991.     app(opt); app('9'); reduce(pp+1,3,base,0,8);
  1992.   else if (cat2==int_like && cat3==lbrace) {
  1993.     big_app1(pp); big_app(' '); big_app1(pp+1); big_app(' '); big_app1(pp+2);
  1994.     reduce(pp,3,exp,-1,9);
  1995. else if (cat1==rbrace) squash(pp,1,stmt,-1,10);
  1996. @ @<Cases for |lpar|@>=
  1997. if ((cat1==exp||cat1==unorbinop) && cat2==rpar) squash(pp,3,exp,-2,11);
  1998. else if (cat1==rpar) {
  1999.   big_app1(pp); app('\\'); app(','); big_app1(pp+1);
  2000. @.\\,@>
  2001.   reduce(pp,2,exp,-2,12);
  2002. else if (cat1==decl_head || cat1==int_like || cat1==exp) {
  2003.   if (cat2==rpar) squash(pp,3,cast,-2,13);
  2004.   else if (cat2==comma) {
  2005.     big_app3(pp); app(opt); app('9'); reduce(pp,3,lpar,0,14);
  2006. else if (cat1==stmt || cat1==decl) {
  2007.   big_app2(pp); big_app(' '); reduce(pp,2,lpar,0,15);
  2008. @ @<Cases for |question|@>=
  2009. if (cat1==exp && cat2==colon) squash(pp,3,binop,-2,16);
  2010. @ @<Cases for |unop|@>=
  2011. if (cat1==exp || cat1==int_like) squash(pp,2,cat1,-2,17);
  2012. @ @<Cases for |unorbinop|@>=
  2013. if (cat1==exp || cat1==int_like) {
  2014.   big_app('{'); big_app1(pp); big_app('}'); big_app1(pp+1);
  2015.   reduce(pp,2,cat1,-2,18);
  2016. else if (cat1==binop) {
  2017.   big_app(math_rel); big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
  2018.   big_app('}'); reduce(pp,2,binop,-1,19);
  2019. @ @<Cases for |binop|@>=
  2020. if (cat1==binop) {
  2021.   big_app(math_rel); big_app('{'); big_app1(pp); big_app('}');
  2022.   big_app('{'); big_app1(pp+1); big_app('}');
  2023.   big_app('}'); reduce(pp,2,binop,-1,20);
  2024. @ @<Cases for |cast|@>=
  2025. if (cat1==exp) {
  2026.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,21);
  2027. else if (cat1==semi) squash(pp,1,exp,-2,22);
  2028. @ @<Cases for |sizeof_like|@>=
  2029. if (cat1==cast) squash(pp,2,exp,-2,23);
  2030. else if (cat1==exp) {
  2031.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,24);
  2032. @ @<Cases for |int_like|@>=
  2033. if (cat1==int_like|| cat1==struct_like) {
  2034.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,cat1,-2,25);
  2035. else if (cat1==exp && (cat2==raw_int||cat2==struct_like))
  2036.   squash(pp,2,int_like,-2,26);
  2037. else if (cat1==exp || cat1==unorbinop || cat1==semi) {
  2038.   big_app1(pp);
  2039.   if (cat1!=semi) big_app(' ');
  2040.   reduce(pp,1,decl_head,-1,27);
  2041. else if (cat1==colon) {
  2042.   big_app1(pp); big_app(' '); reduce(pp,1,decl_head,0,28);
  2043. else if (cat1==prelangle) squash(pp+1,1,langle,1,29);
  2044. else if (cat1==colcol && (cat2==exp||cat2==int_like)) squash(pp,3,cat2,-2,30);
  2045. else if (cat1==cast) {
  2046.   if (cat2==lbrace) {
  2047.   big_app2(pp); big_app(indent); big_app(indent);
  2048.   reduce(pp,2,fn_decl,1,31);
  2049.   else squash(pp,2,int_like,-2,32);
  2050. @ @<Cases for |decl_head|@>=
  2051. if (cat1==comma) {
  2052.   big_app2(pp); big_app(' '); reduce(pp,2,decl_head,-1,33);
  2053. else if (cat1==unorbinop) {
  2054.   big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
  2055.   reduce(pp,2,decl_head,-1,34);
  2056. else if (cat1==exp && cat2!=lpar && cat2!=exp) {
  2057.   make_underlined(pp+1); squash(pp,2,decl_head,-1,35);
  2058. else if ((cat1==binop||cat1==colon) && cat2==exp && (cat3==comma ||
  2059.     cat3==semi || cat3==rpar))
  2060.   squash(pp,3,decl_head,-1,36);
  2061. else if (cat1==cast) squash(pp,2,decl_head,-1,37);
  2062. else if (cat1==lbrace || (cat1==int_like&&cat2!=colcol) || cat1==decl) {
  2063.   big_app1(pp); big_app(indent); app(indent); reduce(pp,1,fn_decl,0,38);
  2064. else if (cat1==semi) squash(pp,2,decl,-1,39);
  2065. @ @<Cases for |decl|@>=
  2066. if (cat1==decl) {
  2067.   big_app1(pp); big_app(force); big_app1(pp+1);
  2068.   reduce(pp,2,decl,-1,40);
  2069. else if (cat1==stmt || cat1==function) {
  2070.   big_app1(pp); big_app(big_force);
  2071.   big_app1(pp+1); reduce(pp,2,cat1,-1,41);
  2072. @ @<Cases for |typedef_like|@>=
  2073. if (cat1==decl_head)
  2074.   if ((cat2==exp&&cat3!=lpar&&cat3!=exp)||cat2==int_like) {
  2075.     make_underlined(pp+2); make_reserved(pp+2);
  2076.     big_app2(pp+1); reduce(pp+1,2,decl_head,0,42);
  2077.   else if (cat2==semi) {
  2078.     big_app1(pp); big_app(' '); big_app2(pp+1); reduce(pp,3,decl,-1,43);
  2079. @ @<Cases for |struct_like|@>=
  2080. if (cat1==lbrace) {
  2081.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,struct_head,0,44);
  2082. else if (cat1==exp||cat1==int_like) {
  2083.   if (cat2==lbrace || cat2==semi) {
  2084.     make_underlined(pp+1); make_reserved(pp+1);
  2085.     big_app1(pp); big_app(' '); big_app1(pp+1);
  2086.     if (cat2==semi) reduce(pp,2,decl_head,0,45);
  2087.     else {
  2088.       big_app(' '); big_app1(pp+2);reduce(pp,3,struct_head,0,46);
  2089.     }
  2090.   else if (cat2==colon) squash(pp+2,1,base,-1,47);
  2091.   else if (cat2!=base) {
  2092.     big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,int_like,-2,48);
  2093. @ @<Cases for |struct_head|@>=
  2094. if ((cat1==decl || cat1==stmt || cat1==function) && cat2==rbrace) {
  2095.   big_app1(pp); big_app(indent); big_app(force); big_app1(pp+1);
  2096.   big_app(outdent); big_app(force);  big_app1(pp+2);
  2097.   reduce(pp,3,int_like,-2,49);
  2098. else if (cat1==rbrace) {
  2099.   big_app1(pp); app_str("\\,"); big_app1(pp+1);
  2100. @.\\,@>
  2101.   reduce(pp,2,int_like,-2,50);
  2102. @ @<Cases for |fn_decl|@>=
  2103. if (cat1==decl) {
  2104.   big_app1(pp); big_app(force); big_app1(pp+1); reduce(pp,2,fn_decl,0,51);
  2105. else if (cat1==stmt) {
  2106.   big_app1(pp); app(outdent); app(outdent); big_app(force);
  2107.   big_app1(pp+1); reduce(pp,2,function,-1,52);
  2108. @ @<Cases for |function|@>=
  2109. if (cat1==function || cat1==decl || cat1==stmt) {
  2110.   big_app1(pp); big_app(big_force); big_app1(pp+1); reduce(pp,2,cat1,-1,53);
  2111. @ @<Cases for |lbrace|@>=
  2112. if (cat1==rbrace) {
  2113.   big_app1(pp); app('\\'); app(','); big_app1(pp+1);
  2114. @.\\,@>
  2115.   reduce(pp,2,stmt,-1,54);
  2116. else if ((cat1==stmt||cat1==decl||cat1==function) && cat2==rbrace) {
  2117.   big_app(force); big_app1(pp);  big_app(indent); big_app(force);
  2118.   big_app1(pp+1); big_app(force); big_app(backup);  big_app1(pp+2);
  2119.   big_app(outdent); big_app(force); reduce(pp,3,stmt,-1,55);
  2120. else if (cat1==exp) {
  2121.   if (cat2==rbrace) squash(pp,3,exp,-2,56);
  2122.   else if (cat2==comma && cat3==rbrace) squash(pp,4,exp,-2,56);
  2123. @ @<Cases for |if_like|@>=
  2124. if (cat1==exp) {
  2125.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,if_clause,0,57);
  2126. @ @<Cases for |for_like|@>=
  2127. if (cat1==exp) {
  2128.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,else_like,-2,58);
  2129. @ @<Cases for |else_like|@>=
  2130. if (cat1==lbrace) squash(pp,1,else_head,0,59);
  2131. else if (cat1==stmt) {
  2132.   big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
  2133.   big_app1(pp+1); big_app(outdent); big_app(force);
  2134.   reduce(pp,2,stmt,-1,60);
  2135. @ @<Cases for |else_head|@>=
  2136. if (cat1==stmt || cat1==exp) {
  2137.   big_app(force); big_app1(pp); big_app(break_space); app(noop);
  2138.   big_app(cancel); big_app1(pp+1); big_app(force);
  2139.   reduce(pp,2,stmt,-1,61);
  2140. @ @<Cases for |if_clause|@>=
  2141. if (cat1==lbrace) squash(pp,1,if_head,0,62);
  2142. else if (cat1==stmt) {
  2143.   if (cat2==else_like) {
  2144.     big_app(force); big_app1(pp); big_app(indent); big_app(break_space);
  2145.     big_app1(pp+1); big_app(outdent); big_app(force); big_app1(pp+2);
  2146.     if (cat3==if_like) {
  2147.       big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,63);
  2148.     }@+else reduce(pp,3,else_like,0,64);
  2149.   else squash(pp,1,else_like,0,65);
  2150. @ @<Cases for |if_head|@>=
  2151. if (cat1==stmt || cat1==exp) {
  2152.   if (cat2==else_like) {
  2153.     big_app(force); big_app1(pp); big_app(break_space); app(noop);
  2154.     big_app(cancel); big_app1(pp+1); big_app(force); big_app1(pp+2);
  2155.     if (cat3==if_like) {
  2156.       big_app(' '); big_app1(pp+3); reduce(pp,4,if_like,0,66);
  2157.     }@+else reduce(pp,3,else_like,0,67);
  2158.   else squash(pp,1,else_head,0,68);
  2159. @ @<Cases for |do_like|@>=
  2160. if (cat1==stmt && cat2==else_like && cat3==semi) {
  2161.   big_app1(pp); big_app(break_space); app(noop); big_app(cancel);
  2162.   big_app1(pp+1); big_app(cancel); app(noop); big_app(break_space);
  2163.   big_app2(pp+2); reduce(pp,4,stmt,-1,69);
  2164. @ @<Cases for |case_like|@>=
  2165. if (cat1==semi) squash(pp,2,stmt,-1,70);
  2166. else if (cat1==colon) squash(pp,2,tag,-1,71);
  2167. else if (cat1==exp) {
  2168.   if (cat2==semi) {
  2169.     big_app1(pp); big_app(' ');  big_app1(pp+1);  big_app1(pp+2);
  2170.     reduce(pp,3,stmt,-1,72);
  2171.   else if (cat2==colon) {
  2172.     big_app1(pp); big_app(' ');  big_app1(pp+1);  big_app1(pp+2);
  2173.     reduce(pp,3,tag,-1,73);
  2174. @ @<Cases for |tag|@>=
  2175. if (cat1==tag) {
  2176.   big_app1(pp); big_app(break_space); big_app1(pp+1); reduce(pp,2,tag,-1,74);
  2177. else if (cat1==stmt||cat1==decl||cat1==function) {
  2178.   big_app(force); big_app(backup); big_app1(pp); big_app(break_space);
  2179.   big_app1(pp+1); reduce(pp,2,cat1,-1,75);
  2180. @ The user can decide at run-time whether short statements should be
  2181. grouped together on the same line.
  2182. @d force_lines flags['f'] /* should each statement be on its own line? */
  2183. @<Cases for |stmt|@>=
  2184. if (cat1==stmt||cat1==decl||cat1==function) {
  2185.   big_app1(pp);
  2186.   if (cat1==function) big_app(big_force);
  2187.   else if (cat1==decl) big_app(big_force);
  2188.   else if (force_lines) big_app(force);
  2189.   else big_app(break_space);
  2190.   big_app1(pp+1); reduce(pp,2,cat1,-1,76);
  2191. @ @<Cases for |semi|@>=
  2192. big_app(' '); big_app1(pp); reduce(pp,1,stmt,-1,77);
  2193. @ @<Cases for |lproc|@>=
  2194. if (cat1==define_like) make_underlined(pp+2);
  2195. if (cat1==else_like || cat1==if_like ||cat1==define_like)
  2196.   squash(pp,2,lproc,0,78);
  2197. else if (cat1==rproc) {
  2198.   app(inserted); big_app2(pp); reduce(pp,2,insert,-1,79);
  2199. } else if (cat1==exp || cat1==function) {
  2200.   if (cat2==rproc) {
  2201.     app(inserted); big_app1(pp); big_app(' '); big_app2(pp+1);
  2202.     reduce(pp,3,insert,-1,80);
  2203.   else if (cat2==exp && cat3==rproc && cat1==exp) {
  2204.     app(inserted); big_app1(pp); big_app(' '); big_app1(pp+1); app_str(" \\5");
  2205. @.\\5@>
  2206.     big_app2(pp+2); reduce(pp,4,insert,-1,80);
  2207. @ @<Cases for |section_scrap|@>=
  2208. if (cat1==semi) {
  2209.   big_app2(pp); big_app(force); reduce(pp,2,stmt,-2,81);
  2210. else squash(pp,1,exp,-2,82);
  2211. @ @<Cases for |insert|@>=
  2212. if (cat1)
  2213.   squash(pp,2,cat1,0,83);
  2214. @ @<Cases for |prelangle|@>=
  2215. init_mathness=cur_mathness=yes_math;
  2216. app('<'); reduce(pp,1,binop,-2,84);
  2217. @ @<Cases for |prerangle|@>=
  2218. init_mathness=cur_mathness=yes_math;
  2219. app('>'); reduce(pp,1,binop,-2,85);
  2220. @ @<Cases for |langle|@>=
  2221. if (cat1==exp && cat2==prerangle) squash(pp,3,cast,-1,86);
  2222. else if (cat1==prerangle) {
  2223.   big_app1(pp); app('\\'); app(','); big_app1(pp+1);
  2224. @.\\,@>
  2225.   reduce(pp,2,cast,-1,87);
  2226. else if (cat1==decl_head || cat1==int_like) {
  2227.   if (cat2==prerangle) squash(pp,3,cast,-1,88);
  2228.   else if (cat2==comma) {
  2229.     big_app3(pp); app(opt); app('9'); reduce(pp,3,langle,0,89);
  2230. @ @<Cases for |public_like|@>=
  2231. if (cat1==colon) squash(pp,2,tag,-1,90);
  2232. else squash(pp,1,int_like,-2,91);
  2233. @ @<Cases for |colcol|@>=
  2234. if (cat1==exp||cat1==int_like) squash(pp,2,cat1,-2,92);
  2235. @ @<Cases for |new_like|@>=
  2236. if (cat1==exp || (cat1==raw_int&&cat2!=prelangle&&cat2!=langle)) {
  2237.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,new_like,0,93);
  2238. else if (cat1==raw_unorbin || cat1==colcol)
  2239.   squash(pp,2,new_like,0,94);
  2240. else if (cat1==cast) squash(pp,2,exp,-2,95);
  2241. else if (cat1!=lpar && cat1!=raw_int && cat1!=struct_like)
  2242.   squash(pp,1,exp,-2,96);
  2243. @ @<Cases for |operator_like|@>=
  2244. if (cat1==binop || cat1==unop || cat1==unorbinop) {
  2245.   if (cat2==binop) break;
  2246.   big_app1(pp); big_app('{'); big_app1(pp+1); big_app('}');
  2247.   reduce(pp,2,exp,-2,97);
  2248. else if (cat1==new_like || cat1==sizeof_like) {
  2249.   big_app1(pp); big_app(' '); big_app1(pp+1); reduce(pp,2,exp,-2,98);
  2250. else squash(pp,1,new_like,0,99);
  2251. @ @<Cases for |catch_like|@>=
  2252. if (cat1==cast || cat1==exp) {
  2253.   big_app2(pp); big_app(indent); big_app(indent);
  2254.   reduce(pp,2,fn_decl,0,100);
  2255. @ @<Cases for |base|@>=
  2256. if (cat1==public_like && cat2==exp) {
  2257.   if (cat3==comma) {
  2258.     big_app2(pp); big_app(' '); big_app2(pp+2);
  2259.     reduce(pp,4,base,0,101);
  2260.   } else {
  2261.     big_app1(pp+1); big_app(' '); big_app1(pp+2);
  2262.     reduce(pp+1,2,int_like,-1,102);
  2263. @ @<Cases for |raw_rpar|@>=
  2264. if (cat1==const_like) {
  2265.   big_app1(pp); big_app(' ');
  2266.   big_app1(pp+1); reduce(pp,2,raw_rpar,0,103);
  2267. } else squash(pp,1,rpar,-3,104);
  2268. @ @<Cases for |raw_unorbin|@>=
  2269. if (cat1==const_like) {
  2270.   big_app2(pp); app_str("\\ "); reduce(pp,2,raw_unorbin,0,105);
  2271. @.\\ @>
  2272. } else squash(pp,1,unorbinop,-2,106);
  2273. @ @<Cases for |const_like|@>=
  2274. squash(pp,1,int_like,-2,107);
  2275. @ @<Cases for |raw_int|@>=
  2276. if (cat1==lpar) squash(pp,1,exp,-2,108);
  2277. else squash(pp,1,int_like,-3,109);
  2278. @ The `|freeze_text|' macro is used to give official status to a token list.
  2279. Before saying |freeze_text|, items are appended to the current token list,
  2280. and we know that the eventual number of this token list will be the current
  2281. value of |text_ptr|. But no list of that number really exists as yet,
  2282. because no ending point for the current list has been
  2283. stored in the |tok_start| array. After saying |freeze_text|, the
  2284. old current token list becomes legitimate, and its number is the current
  2285. value of |text_ptr-1| since |text_ptr| has been increased. The new
  2286. current token list is empty and ready to be appended to.
  2287. Note that |freeze_text| does not check to see that |text_ptr| hasn't gotten
  2288. too large, since it is assumed that this test was done beforehand.
  2289. @d freeze_text *(++text_ptr)=tok_ptr
  2290. @ Here's the |reduce| procedure used in our code for productions:
  2291. reduce(j,k,c,d,n)
  2292. scrap_pointer j;
  2293. eight_bits c;
  2294. short k, d, n;
  2295.   scrap_pointer i, i1; /* pointers into scrap memory */
  2296.   j->cat=c; j->trans=text_ptr;
  2297.   j->mathness=4*cur_mathness+init_mathness;
  2298.   freeze_text;
  2299.   if (k>1) {
  2300.     for (i=j+k, i1=j+1; i<=lo_ptr; i++, i1++) {
  2301.       i1->cat=i->cat; i1->trans=i->trans;
  2302.       i1->mathness=i->mathness;
  2303.     }
  2304.     lo_ptr=lo_ptr-k+1;
  2305.   @<Change |pp| to $\max(|scrap_base|,|pp|+d)$@>;
  2306.   @<Print a snapshot of the scrap list if debugging @>;
  2307.   pp--; /* we next say |pp++| */
  2308. @ @<Change |pp| to $\max...@>=
  2309. if (pp+d>=scrap_base) pp=pp+d;
  2310. else pp=scrap_base;
  2311. @ Here's the |squash| procedure, which
  2312. takes advantage of the simplification that occurs when |k==1|.
  2313. squash(j,k,c,d,n)
  2314. scrap_pointer j;
  2315. eight_bits c;
  2316. short k, d, n;
  2317.   scrap_pointer i; /* pointers into scrap memory */
  2318.   if (k==1) {
  2319.     j->cat=c; @<Change |pp|...@>;
  2320.     @<Print a snapshot...@>;
  2321.     pp--; /* we next say |pp++| */
  2322.     return;
  2323.   for (i=j; i<j+k; i++) big_app1(i);
  2324.   reduce(j,k,c,d,n);
  2325. @ Here now is the code that applies productions as long as possible.
  2326. Before applying the production mechanism, we must make sure
  2327. it has good input (at least four scraps, the length of the lhs of the
  2328. longest rules), and that there is enough room in the memory arrays
  2329. to hold the appended tokens and texts.  Here we use a very
  2330. conservative test: it's more important to make sure the program
  2331. will still work if we change the production rules (within reason)
  2332. than to squeeze the last bit of space from the memory arrays.
  2333. @d safe_tok_incr 20
  2334. @d safe_text_incr 10
  2335. @d safe_scrap_incr 10
  2336. @<Reduce the scraps using the productions until no more rules apply@>=
  2337. while (1) {
  2338.   @<Make sure the entries |pp| through |pp+3| of |cat| are defined@>;
  2339.   if (tok_ptr+safe_tok_incr>tok_mem_end) {
  2340.     if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  2341.     overflow("token");
  2342.   if (text_ptr+safe_text_incr>tok_start_end) {
  2343.     if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  2344.     overflow("text");
  2345.   if (pp>lo_ptr) break;
  2346.   init_mathness=cur_mathness=maybe_math;
  2347.   @<Match a production...@>;
  2348. @ If we get to the end of the scrap list, category codes equal to zero are
  2349. stored, since zero does not match anything in a production.
  2350. @<Make sure the entries...@>=
  2351. if (lo_ptr<pp+3) {
  2352.   while (hi_ptr<=scrap_ptr && lo_ptr!=pp+3) {
  2353.     (++lo_ptr)->cat=hi_ptr->cat; lo_ptr->mathness=(hi_ptr)->mathness;
  2354.     lo_ptr->trans=(hi_ptr++)->trans;
  2355.   for (i=lo_ptr+1;i<=pp+3;i++) i->cat=0;
  2356. @ If \.{CWEAVE} is being run in debugging mode, the production numbers and
  2357. current stack categories will be printed out when |tracing| is set to 2;
  2358. a sequence of two or more irreducible scraps will be printed out when
  2359. |tracing| is set to 1.
  2360. @<Global...@>=
  2361. int tracing; /* can be used to show parsing details */
  2362. @ @<Print a snapsh...@>=
  2363. { scrap_pointer k; /* pointer into |scrap_info| */
  2364.   if (tracing==2) {
  2365.     printf("\n%d:",n);
  2366.     for (k=scrap_base; k<=lo_ptr; k++) {
  2367.       if (k==pp) putxchar('*'); else putxchar(' ');
  2368.       if (k->mathness %4 ==  yes_math) putchar('+');
  2369.       else if (k->mathness %4 ==  no_math) putchar('-');
  2370.       print_cat(k->cat);
  2371.       if (k->mathness /4 ==  yes_math) putchar('+');
  2372.       else if (k->mathness /4 ==  no_math) putchar('-');
  2373.     }
  2374.     if (hi_ptr<=scrap_ptr) printf("..."); /* indicate that more is coming */
  2375. @ The |translate| function assumes that scraps have been stored in
  2376. positions |scrap_base| through |scrap_ptr| of |cat| and |trans|. It
  2377. applies productions as much as
  2378. possible. The result is a token list containing the translation of
  2379. the given sequence of scraps.
  2380. After calling |translate|, we will have |text_ptr+3<=max_texts| and
  2381. |tok_ptr+6<=max_toks|, so it will be possible to create up to three token
  2382. lists with up to six tokens without checking for overflow. Before calling
  2383. |translate|, we should have |text_ptr<max_texts| and |scrap_ptr<max_scraps|,
  2384. since |translate| might add a new text and a new scrap before it checks
  2385. for overflow.
  2386. text_pointer
  2387. translate() /* converts a sequence of scraps */
  2388.   scrap_pointer i, /* index into |cat| */
  2389.   j; /* runs through final scraps */
  2390.   pp=scrap_base; lo_ptr=pp-1; hi_ptr=pp;
  2391.   @<If tracing, print an indication of where we are@>;
  2392.   @<Reduce the scraps...@>;
  2393.   @<Combine the irreducible scraps that remain@>;
  2394. @ If the initial sequence of scraps does not reduce to a single scrap,
  2395. we concatenate the translations of all remaining scraps, separated by
  2396. blank spaces, with dollar signs surrounding the translations of scraps
  2397. where appropriate.
  2398. @<Combine the irreducible...@>= {
  2399.   @<If semi-tracing, show the irreducible scraps@>;
  2400.   for (j=scrap_base; j<=lo_ptr; j++) {
  2401.     if (j!=scrap_base) app(' ');
  2402.     if (j->mathness % 4 == yes_math) app('$');
  2403.     app1(j);
  2404.     if (j->mathness / 4 == yes_math) app('$');
  2405.     if (tok_ptr+6>tok_mem_end) overflow("token");
  2406.   freeze_text; return(text_ptr-1);
  2407. @ @<If semi-tracing, show the irreducible scraps@>=
  2408. if (lo_ptr>scrap_base && tracing==1) {
  2409.   printf("\nIrreducible scrap sequence in section %d:",section_count);
  2410. @.Irreducible scrap sequence...@>
  2411.   mark_harmless;
  2412.   for (j=scrap_base; j<=lo_ptr; j++) {
  2413.     printf(" "); print_cat(j->cat);
  2414. @ @<If tracing,...@>=
  2415. if (tracing==2) {
  2416.   printf("\nTracing after l. %d:\n",cur_line); mark_harmless;
  2417. @.Tracing after...@>
  2418.   if (loc>buffer+50) {
  2419.     printf("...");
  2420.     term_write(loc-51,51);
  2421.   else term_write(buffer,loc-buffer);
  2422. @* Initializing the scraps.
  2423. If we are going to use the powerful production mechanism just developed, we
  2424. must get the scraps set up in the first place, given a \CEE/ text. A table
  2425. of the initial scraps corresponding to \CEE/ tokens appeared above in the
  2426. section on parsing; our goal now is to implement that table. We shall do this
  2427. by implementing a subroutine called |C_parse| that is analogous to the
  2428. |C_xref| routine used during phase one.
  2429. Like |C_xref|, the |C_parse| procedure starts with the current
  2430. value of |next_control| and it uses the operation |next_control=get_next()|
  2431. repeatedly to read \CEE/ text until encountering the next `\.{\v}' or
  2432. `\.{/*}', or until |next_control>=format_code|. The scraps corresponding to
  2433. what it reads are appended into the |cat| and |trans| arrays, and |scrap_ptr|
  2434. is advanced.
  2435. C_parse(spec_ctrl) /* creates scraps from \CEE/ tokens */
  2436.   eight_bits spec_ctrl;
  2437.   int count; /* characters remaining before string break */
  2438.   while (next_control<format_code || next_control==spec_ctrl) {
  2439.     @<Append the scrap appropriate to |next_control|@>;
  2440.     next_control=get_next();
  2441.     if (next_control=='|' || next_control==begin_comment ||
  2442.         next_control==begin_short_comment) return;
  2443. @ The following macro is used to append a scrap whose tokens have just
  2444. been appended:
  2445. @d app_scrap(c,b) {
  2446.   (++scrap_ptr)->cat=(c); scrap_ptr->trans=text_ptr;
  2447.   scrap_ptr->mathness=5*(b); /* no no, yes yes, or maybe maybe */
  2448.   freeze_text;
  2449. @ @<Append the scr...@>=
  2450. @<Make sure that there is room for the new scraps, tokens, and texts@>;
  2451. switch (next_control) {
  2452.   case section_name:
  2453.     app(section_flag+(int)(cur_section-name_dir));
  2454.     app_scrap(section_scrap,maybe_math);
  2455.     app_scrap(exp,yes_math);@+break;
  2456.   case string: case constant: case verbatim: @<Append a string or constant@>;
  2457.    @+break;
  2458.   case identifier: app_cur_id(1);@+break;
  2459.   case TeX_string: @<Append a \TEX/ string, without forming a scrap@>;@+break;
  2460.   case '/': case '.':
  2461.     app(next_control); app_scrap(binop,yes_math);@+break;
  2462.   case '<': app_str("\\langle");@+app_scrap(prelangle,yes_math);@+break;
  2463. @.\\langle@>
  2464.   case '>': app_str("\\rangle");@+app_scrap(prerangle,yes_math);@+break;
  2465. @.\\rangle@>
  2466.   case '=': app_str("\\K"); app_scrap(binop,yes_math);@+break;
  2467. @.\\K@>
  2468.   case '|': app_str("\\OR"); app_scrap(binop,yes_math);@+break;
  2469. @.\\OR@>
  2470.   case '^': app_str("\\XOR"); app_scrap(binop,yes_math);@+break;
  2471. @.\\XOR@>
  2472.   case '%': app_str("\\MOD"); app_scrap(binop,yes_math);@+break;
  2473. @.\\MOD@>
  2474.   case '!': app_str("\\R"); app_scrap(unop,yes_math);@+break;
  2475. @.\\R@>
  2476.   case '~': app_str("\\CM"); app_scrap(unop,yes_math);@+break;
  2477. @.\\CM@>
  2478.   case '+': case '-': app(next_control); app_scrap(unorbinop,yes_math);@+break;
  2479.   case '*': app(next_control); app_scrap(raw_unorbin,yes_math);@+break;
  2480.   case '&': app_str("\\AND"); app_scrap(raw_unorbin,yes_math);@+break;
  2481. @.\\AND@>
  2482.   case '?': app_str("\\?"); app_scrap(question,yes_math);@+break;
  2483. @.\\?@>
  2484.   case '#': app_str("\\#"); app_scrap(unorbinop,yes_math);@+break;
  2485. @.\\\#@>
  2486.   case ignore: case xref_roman: case xref_wildcard:
  2487.   case xref_typewriter: case noop:@+break;
  2488.   case '(': case '[': app(next_control); app_scrap(lpar,maybe_math);@+break;
  2489.   case ')': case ']': app(next_control); app_scrap(raw_rpar,maybe_math);@+break;
  2490.   case '{': app_str("\\{"@q}@>); app_scrap(lbrace,yes_math);@+break;
  2491. @.\\\{@>@q}@>
  2492.   case '}': app_str(@q{@>"\\}"); app_scrap(rbrace,yes_math);@+break;
  2493. @q{@>@.\\\}@>
  2494.   case ',': app(','); app_scrap(comma,yes_math);@+break;
  2495.   case ';': app(';'); app_scrap(semi,maybe_math);@+break;
  2496.   case ':': app(':'); app_scrap(colon,maybe_math);@+break;@/
  2497.   @t\4@>  @<Cases involving nonstandard characters@>@;
  2498.   case thin_space: app_str("\\,"); app_scrap(insert,maybe_math);@+break;
  2499. @.\\,@>
  2500.   case math_break: app(opt); app_str("0");
  2501.     app_scrap(insert,maybe_math);@+break;
  2502.   case line_break: app(force); app_scrap(insert,no_math);@+break;
  2503.   case left_preproc: app(force); app(preproc_line);
  2504.     app_str("\\#"); app_scrap(lproc,no_math);@+break;
  2505. @.\\\#@>
  2506.   case right_preproc: app(force); app_scrap(rproc,no_math);@+break;
  2507.   case big_line_break: app(big_force); app_scrap(insert,no_math);@+break;
  2508.   case no_line_break: app(big_cancel); app(noop); app(break_space);
  2509.     app(noop); app(big_cancel);
  2510.     app_scrap(insert,no_math);@+break;
  2511.   case pseudo_semi: app_scrap(semi,maybe_math);@+break;
  2512.   case macro_arg_open: app_scrap(begin_arg,maybe_math);@+break;
  2513.   case macro_arg_close: app_scrap(end_arg,maybe_math);@+break;
  2514.   case join: app_str("\\J"); app_scrap(insert,no_math);@+break;
  2515. @.\\J@>
  2516.   case output_defs_code: app(force); app_str("\\ATH"); app(force);
  2517.     app_scrap(insert,no_math);@+break;
  2518. @.\\ATH@>
  2519.   default: app(inserted); app(next_control);
  2520.     app_scrap(insert,maybe_math);@+break;
  2521. @ @<Make sure that there is room for the new...@>=
  2522. if (scrap_ptr+safe_scrap_incr>scrap_info_end ||
  2523.   tok_ptr+safe_tok_incr>tok_mem_end @| ||
  2524.   text_ptr+safe_text_incr>tok_start_end) {
  2525.   if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  2526.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  2527.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  2528.   overflow("scrap/token/text");
  2529. @ Some nonstandard characters may have entered \.{CWEAVE} by means of
  2530. standard ones. They are converted to \TEX/ control sequences so that it is
  2531. possible to keep \.{CWEAVE} from outputting unusual |char| codes.
  2532. @<Cases involving nonstandard...@>=
  2533. case not_eq: app_str("\\I");@+app_scrap(binop,yes_math);@+break;
  2534. @.\\I@>
  2535. case lt_eq: app_str("\\Z");@+app_scrap(binop,yes_math);@+break;
  2536. @.\\Z@>
  2537. case gt_eq: app_str("\\G");@+app_scrap(binop,yes_math);@+break;
  2538. @.\\G@>
  2539. case eq_eq: app_str("\\E");@+app_scrap(binop,yes_math);@+break;
  2540. @.\\E@>
  2541. case and_and: app_str("\\W");@+app_scrap(binop,yes_math);@+break;
  2542. @.\\W@>
  2543. case or_or: app_str("\\V");@+app_scrap(binop,yes_math);@+break;
  2544. @.\\V@>
  2545. case plus_plus: app_str("\\PP");@+app_scrap(unop,yes_math);@+break;
  2546. @.\\PP@>
  2547. case minus_minus: app_str("\\MM");@+app_scrap(unop,yes_math);@+break;
  2548. @.\\MM@>
  2549. case minus_gt: app_str("\\MG");@+app_scrap(binop,yes_math);@+break;
  2550. @.\\MG@>
  2551. case gt_gt: app_str("\\GG");@+app_scrap(binop,yes_math);@+break;
  2552. @.\\GG@>
  2553. case lt_lt: app_str("\\LL");@+app_scrap(binop,yes_math);@+break;
  2554. @.\\LL@>
  2555. case dot_dot_dot: app_str("\\,\\ldots\\,");@+app_scrap(exp,yes_math);@+break;
  2556. @.\\,@>
  2557. @.\\ldots@>
  2558. case colon_colon: app_str("\\DC");@+app_scrap(colcol,maybe_math);@+break;
  2559. @.\\DC@>
  2560. case period_ast: app_str("\\PA");@+app_scrap(binop,yes_math);@+break;
  2561. @.\\PA@>
  2562. case minus_gt_ast: app_str("\\MGA");@+app_scrap(binop,yes_math);@+break;
  2563. @.\\MGA@>
  2564. @ The following code must use |app_tok| instead of |app| in order to
  2565. protect against overflow. Note that |tok_ptr+1<=max_toks| after |app_tok|
  2566. has been used, so another |app| is legitimate before testing again.
  2567. Many of the special characters in a string must be prefixed by `\.\\' so that
  2568. \TEX/ will print them properly.
  2569. @^special string characters@>
  2570. @<Append a string or...@>=
  2571. count= -1;
  2572. if (next_control==constant) app_str("\\T{"@q}@>);
  2573. @.\\T@>
  2574. else if (next_control==string) {
  2575.   count=20; app_str("\\.{"@q}@>);
  2576. @.\\.@>
  2577. else app_str("\\vb{"@q}@>);
  2578. @.\\vb@>
  2579. while (id_first<id_loc) {
  2580.   if (count==0) { /* insert a discretionary break in a long string */
  2581.      app_str(@q(@>@q{@>"}\\)\\.{"@q}@>); count=20;
  2582. @q(@>@.\\)@>
  2583. @^high-bit character handling@>
  2584.   if((eight_bits)(*id_first)>0177) {
  2585.     app_tok(quoted_char);
  2586.     app_tok((eight_bits)(*id_first++));
  2587.   else {
  2588.     switch (*id_first) {
  2589.       case  ' ':case '\\':case '#':case '%':case '$':case '^':
  2590.       case '{': case '}': case '~': case '&': case '_': app('\\'); break;
  2591. @.\\\ @>
  2592. @.\\\\@>
  2593. @.\\\#@>
  2594. @.\\\%@>
  2595. @.\\\$@>
  2596. @.\\\^@>
  2597. @.\\\{@>@q}@>
  2598. @q{@>@.\\\}@>
  2599. @.\\\~@>
  2600. @.\\\&@>
  2601. @.\\_@>  @q CWEAVE does quote an underscore! @>
  2602.       case '@@': if (*(id_first+1)=='@@') id_first++;
  2603.         else err_print("! Double @@ should be used in strings");
  2604. @.Double @@ should be used...@>
  2605.     }
  2606.     app_tok(*id_first++);
  2607.   count--;
  2608. app(@q{@>'}');
  2609. app_scrap(exp,maybe_math);
  2610. @ We do not make the \TEX/ string into a scrap, because there is no
  2611. telling what the user will be putting into it; instead we leave it
  2612. open, to be picked up by next scrap. If it comes at the end of a
  2613. section, it will be made into a scrap when |finish_C| is called.
  2614. @<Append a \TEX/ string, without forming a scrap@>=
  2615. app_str("\\hbox{"@q}@>);
  2616. @^high-bit character handling@>
  2617. while (id_first<id_loc)
  2618.   if((eight_bits)(*id_first)>0177) {
  2619.     app_tok(quoted_char);
  2620.     app_tok((eight_bits)(*id_first++));
  2621.   else {
  2622.     if (*id_first=='@@') id_first++;
  2623.     app_tok(*id_first++);
  2624. app(@q{@>'}');
  2625. @ The function |app_cur_id| appends the current identifier to the
  2626. token list; it also builds a new scrap if |scrapping==1|.
  2627. @<Predec...@>=
  2628. void app_cur_id();
  2629. app_cur_id(scrapping)
  2630. boolean scrapping; /* are we making this into a scrap? */
  2631.   name_pointer p=id_lookup(id_first,id_loc,normal);
  2632.   if (p->ilk<=quoted) { /* not a reserved word */
  2633.     app(id_flag+(int)(p-name_dir));
  2634.     if (scrapping) app_scrap(exp,p->ilk>=custom? yes_math: maybe_math);
  2635. @.\\NULL@>
  2636.   } else {
  2637.     app(res_flag+(int)(p-name_dir));
  2638.     if (scrapping) app_scrap(p->ilk,maybe_math);
  2639. @ When the `\.{\v}' that introduces \CEE/ text is sensed, a call on
  2640. |C_translate| will return a pointer to the \TEX/ translation of
  2641. that text. If scraps exist in |scrap_info|, they are
  2642. unaffected by this translation process.
  2643. text_pointer
  2644. C_translate()
  2645.   text_pointer p; /* points to the translation */
  2646.   scrap_pointer save_base; /* holds original value of |scrap_base| */
  2647.   save_base=scrap_base; scrap_base=scrap_ptr+1;
  2648.   C_parse(section_name); /* get the scraps together */
  2649.   if (next_control!='|') err_print("! Missing '|' after C text");
  2650. @.Missing '|'...@>
  2651.   app_tok(cancel); app_scrap(insert,maybe_math);
  2652.         /* place a |cancel| token as a final ``comment'' */
  2653.   p=translate(); /* make the translation */
  2654.   if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  2655.   scrap_ptr=scrap_base-1; scrap_base=save_base; /* scrap the scraps */
  2656.   return(p);
  2657. @ The |outer_parse| routine is to |C_parse| as |outer_xref|
  2658. is to |C_xref|: it constructs a sequence of scraps for \CEE/ text
  2659. until |next_control>=format_code|. Thus, it takes care of embedded comments.
  2660. outer_parse() /* makes scraps from \CEE/ tokens and comments */
  2661.   int bal; /* brace level in comment */
  2662.   text_pointer p, q; /* partial comments */
  2663.   while (next_control<format_code)
  2664.     if (next_control!=begin_comment && next_control!=begin_short_comment)
  2665.       C_parse(ignore);
  2666.     else {
  2667.       boolean is_long_comment=(next_control==begin_comment);
  2668.       @<Make sure that there is room for the new...@>;
  2669.       app(cancel); app(inserted);
  2670.       if (is_long_comment) app_str("\\C{"@q}@>);
  2671. @.\\C@>
  2672.       else app_str("\\SHC{"@q}@>);
  2673. @.\\SHC@>
  2674.       bal=copy_comment(is_long_comment,1); next_control=ignore;
  2675.       while (bal>0) {
  2676.         p=text_ptr; freeze_text; q=C_translate();
  2677.          /* at this point we have |tok_ptr+6<=max_toks| */
  2678.         app(tok_flag+(int)(p-tok_start));
  2679.         app_str("\\PB{"); app(inner_tok_flag+(int)(q-tok_start)); app_tok('}');
  2680. @.\\PB@>
  2681.         if (next_control=='|') {
  2682.           bal=copy_comment(is_long_comment,bal);
  2683.           next_control=ignore;
  2684.         }
  2685.         else bal=0; /* an error has been reported */
  2686.       }
  2687.       app(force); app_scrap(insert,no_math);
  2688.         /* the full comment becomes a scrap */
  2689.     }
  2690. @* Output of tokens.
  2691. So far our programs have only built up multi-layered token lists in
  2692. \.{CWEAVE}'s internal memory; we have to figure out how to get them into
  2693. the desired final form. The job of converting token lists to characters in
  2694. the \TEX/ output file is not difficult, although it is an implicitly
  2695. recursive process. Four main considerations had to be kept in mind when
  2696. this part of \.{CWEAVE} was designed.  (a) There are two modes of output:
  2697. |outer| mode, which translates tokens like |force| into line-breaking
  2698. control sequences, and |inner| mode, which ignores them except that blank
  2699. spaces take the place of line breaks. (b) The |cancel| instruction applies
  2700. to adjacent token or tokens that are output, and this cuts across levels
  2701. of recursion since `|cancel|' occurs at the beginning or end of a token
  2702. list on one level. (c) The \TEX/ output file will be semi-readable if line
  2703. breaks are inserted after the result of tokens like |break_space| and
  2704. |force|.  (d) The final line break should be suppressed, and there should
  2705. be no |force| token output immediately after `\.{\\Y\\B}'.
  2706. @ The output process uses a stack to keep track of what is going on at
  2707. different ``levels'' as the token lists are being written out. Entries on
  2708. this stack have three parts:
  2709. \yskip\hang |end_field| is the |tok_mem| location where the token list of a
  2710. particular level will end;
  2711. \yskip\hang |tok_field| is the |tok_mem| location from which the next token
  2712. on a particular level will be read;
  2713. \yskip\hang |mode_field| is the current mode, either |inner| or |outer|.
  2714. \yskip\noindent The current values of these quantities are referred to
  2715. quite frequently, so they are stored in a separate place instead of in the
  2716. |stack| array. We call the current values |cur_end|, |cur_tok|, and
  2717. |cur_mode|.
  2718. The global variable |stack_ptr| tells how many levels of output are
  2719. currently in progress. The end of output occurs when an |end_translation|
  2720. token is found, so the stack is never empty except when we first begin the
  2721. output process.
  2722. @d inner 0 /* value of |mode| for \CEE/ texts within \TEX/ texts */
  2723. @d outer 1 /* value of |mode| for \CEE/ texts in sections */
  2724. @<Typed...@>= typedef int mode;
  2725. typedef struct {
  2726.   token_pointer end_field; /* ending location of token list */
  2727.   token_pointer tok_field; /* present location within token list */
  2728.   boolean mode_field; /* interpretation of control tokens */
  2729. } output_state;
  2730. typedef output_state *stack_pointer;
  2731. @ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */
  2732. @d cur_tok cur_state.tok_field /* location of next output token in |tok_mem| */
  2733. @d cur_mode cur_state.mode_field /* current mode of interpretation */
  2734. @d init_stack stack_ptr=stack;cur_mode=outer /* initialize the stack */
  2735. @<Global...@>=
  2736. output_state cur_state; /* |cur_end|, |cur_tok|, |cur_mode| */
  2737. output_state stack[stack_size]; /* info for non-current levels */
  2738. stack_pointer stack_ptr; /* first unused location in the output state stack */
  2739. stack_pointer stack_end=stack+stack_size-1; /* end of |stack| */
  2740. stack_pointer max_stack_ptr; /* largest value assumed by |stack_ptr| */
  2741. @ @<Set init...@>=
  2742. max_stack_ptr=stack;
  2743. @ To insert token-list |p| into the output, the |push_level| subroutine
  2744. is called; it saves the old level of output and gets a new one going.
  2745. The value of |cur_mode| is not changed.
  2746. push_level(p) /* suspends the current level */
  2747. text_pointer p;
  2748.   if (stack_ptr==stack_end) overflow("stack");
  2749.   if (stack_ptr>stack) { /* save current state */
  2750.     stack_ptr->end_field=cur_end;
  2751.     stack_ptr->tok_field=cur_tok;
  2752.     stack_ptr->mode_field=cur_mode;
  2753.   stack_ptr++;
  2754.   if (stack_ptr>max_stack_ptr) max_stack_ptr=stack_ptr;
  2755.   cur_tok=*p; cur_end=*(p+1);
  2756. @ Conversely, the |pop_level| routine restores the conditions that were in
  2757. force when the current level was begun. This subroutine will never be
  2758. called when |stack_ptr==1|.
  2759. pop_level()
  2760.   cur_end=(--stack_ptr)->end_field;
  2761.   cur_tok=stack_ptr->tok_field; cur_mode=stack_ptr->mode_field;
  2762. @ The |get_output| function returns the next byte of output that is not a
  2763. reference to a token list. It returns the values |identifier| or |res_word|
  2764. or |section_code| if the next token is to be an identifier (typeset in
  2765. italics), a reserved word (typeset in boldface) or a section name (typeset
  2766. by a complex routine that might generate additional levels of output).
  2767. In these cases |cur_name| points to the identifier or section name in
  2768. question.
  2769. @<Global...@>=
  2770. name_pointer cur_name;
  2771. @ @d res_word 0201 /* returned by |get_output| for reserved words */
  2772. @d section_code 0200 /* returned by |get_output| for section names */
  2773. eight_bits
  2774. get_output() /* returns the next token of output */
  2775.   sixteen_bits a; /* current item read from |tok_mem| */
  2776.   restart: while (cur_tok==cur_end) pop_level();
  2777.   a=*(cur_tok++);
  2778.   if (a>=0400) {
  2779.     cur_name=a % id_flag + name_dir;
  2780.     switch (a / id_flag) {
  2781.       case 2: return(res_word); /* |a==res_flag+cur_name| */
  2782.       case 3: return(section_code); /* |a==section_flag+cur_name| */
  2783.       case 4: push_level(a % id_flag + tok_start); goto restart;
  2784.         /* |a==tok_flag+cur_name| */
  2785.       case 5: push_level(a % id_flag + tok_start); cur_mode=inner; goto restart;
  2786.         /* |a==inner_tok_flag+cur_name| */
  2787.       default: return(identifier); /* |a==id_flag+cur_name| */
  2788.     }
  2789.   return(a);
  2790. @ The real work associated with token output is done by |make_output|.
  2791. This procedure appends an |end_translation| token to the current token list,
  2792. and then it repeatedly calls |get_output| and feeds characters to the output
  2793. buffer until reaching the |end_translation| sentinel. It is possible for
  2794. |make_output| to be called recursively, since a section name may include
  2795. embedded \CEE/ text; however, the depth of recursion never exceeds one
  2796. level, since section names cannot be inside of section names.
  2797. A procedure called |output_C| does the scanning, translation, and
  2798. output of \CEE/ text within `\pb' brackets, and this procedure uses
  2799. |make_output| to output the current token list. Thus, the recursive call
  2800. of |make_output| actually occurs when |make_output| calls |output_C|
  2801. while outputting the name of a section.
  2802. @^recursion@>
  2803. The token list created from within `\pb' brackets is output as an argument
  2804. to \.{\\PB}. Although \.{cwebmac} ignores \.{\\PB}, other macro packages
  2805. might use it to localize the special meaning of the macros that mark up
  2806. program text.
  2807. output_C() /* outputs the current token list */
  2808.   token_pointer save_tok_ptr;
  2809.   text_pointer save_text_ptr;
  2810.   sixteen_bits save_next_control; /* values to be restored */
  2811.   text_pointer p; /* translation of the \CEE/ text */
  2812.   save_tok_ptr=tok_ptr; save_text_ptr=text_ptr;
  2813.   save_next_control=next_control; next_control=ignore; p=C_translate();
  2814.   app(inner_tok_flag+(int)(p-tok_start));
  2815.   out_str("\\PB{"); make_output(); out('}'); /* output the list */
  2816. @.\\PB@>
  2817.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  2818.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  2819.   text_ptr=save_text_ptr; tok_ptr=save_tok_ptr; /* forget the tokens */
  2820.   next_control=save_next_control; /* restore |next_control| to original state */
  2821. @ Here is \.{CWEAVE}'s major output handler.
  2822. @<Predecl...@>=
  2823. void make_output();
  2824. make_output() /* outputs the equivalents of tokens */
  2825.   eight_bits a, /* current output byte */
  2826.   b; /* next output byte */
  2827.   int c; /* count of |indent| and |outdent| tokens */
  2828.   char *k, *k_limit; /* indices into |byte_mem| */
  2829.   char *j; /* index into |buffer| */
  2830.   char delim; /* first and last character of string being copied */
  2831.   char *save_loc, *save_limit; /* |loc| and |limit| to be restored */
  2832.   char scratch[longest_name]; /* scratch area for section names */
  2833.   name_pointer cur_section_name; /* name of section being output */
  2834.   boolean save_mode; /* value of |cur_mode| before a sequence of breaks */
  2835.   app(end_translation); /* append a sentinel */
  2836.   freeze_text; push_level(text_ptr-1);
  2837.   while (1) {
  2838.     a=get_output();
  2839.     reswitch: switch(a) {
  2840.       case end_translation: return;
  2841.       case identifier: case res_word: @<Output an identifier@>; break;
  2842.       case section_code: @<Output a section name@>; break;
  2843.       case math_rel: out_str("\\MRL{"@q}@>);
  2844. @.\\MRL@>
  2845.       case noop: case inserted: break;
  2846.       case cancel: case big_cancel: c=0; b=a;
  2847.         while (1) {
  2848.           a=get_output();
  2849.           if (a==inserted) continue;
  2850.           if ((a<indent && !(b==big_cancel&&a==' ')) || a>big_force) break;
  2851.           if (a==indent) c++; else if (a==outdent) c--;
  2852.           else if (a==opt) a=get_output();
  2853.         }
  2854.         @<Output saved |indent| or |outdent| tokens@>;
  2855.         goto reswitch;
  2856.       case indent: case outdent: case opt: case backup: case break_space:
  2857.       case force: case big_force: case preproc_line: @<Output a control,
  2858.         look ahead in case of line breaks, possibly |goto reswitch|@>; break;
  2859.       case quoted_char: out(*(cur_tok++)); break;
  2860.       default: out(a); /* otherwise |a| is an ordinary character */
  2861.     }
  2862. @ An identifier of length one does not have to be enclosed in braces, and it
  2863. looks slightly better if set in a math-italic font instead of a (slightly
  2864. narrower) text-italic font. Thus we output `\.{\\\v}\.{a}' but
  2865. `\.{\\\\\{aa\}}'.
  2866. @<Output an identifier@>=
  2867. out('\\');
  2868. if (a==identifier) {
  2869.   if (cur_name->ilk>=custom && cur_name->ilk<=quoted && !doing_format) {
  2870.     for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
  2871.       out(isxalpha(*j)? 'x':*j);
  2872.     break;
  2873.   } else if (is_tiny(cur_name)) out('|')
  2874. @.\\|@>
  2875.   else { delim='.';
  2876.     for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
  2877.       if (xislower(*j)) { /* not entirely uppercase */
  2878.          delim='\\'; break;
  2879.       }
  2880.   out(delim);
  2881. @.\\\\@>
  2882. @.\\.@>
  2883. else out('&') /* |a==res_word| */
  2884. @.\\\&@>
  2885. if (is_tiny(cur_name)) {
  2886.   if (isxalpha((cur_name->byte_start)[0]))
  2887.     out('\\');
  2888.   out((cur_name->byte_start)[0]);
  2889. else out_name(cur_name);
  2890. @ The current mode does not affect the behavior of \.{CWEAVE}'s output routine
  2891. except when we are outputting control tokens.
  2892. @<Output a control...@>=
  2893. if (a<break_space || a==preproc_line) {
  2894.   if (cur_mode==outer) {
  2895.     out('\\'); out(a-cancel+'0');
  2896. @.\\1@>
  2897. @.\\2@>
  2898. @.\\3@>
  2899. @.\\4@>
  2900. @.\\8@>
  2901.     if (a==opt) {
  2902.       b=get_output(); /* |opt| is followed by a digit */
  2903.       if (b!='0' || force_lines==0) out(b)@;
  2904.       else out_str("{-1}"); /* |force_lines| encourages more \.{@@\v} breaks */
  2905.     }
  2906.   } else if (a==opt) b=get_output(); /* ignore digit following |opt| */
  2907. else @<Look ahead for strongest line break, |goto reswitch|@>
  2908. @ If several of the tokens |break_space|, |force|, |big_force| occur in a
  2909. row, possibly mixed with blank spaces (which are ignored),
  2910. the largest one is used. A line break also occurs in the output file,
  2911. except at the very end of the translation. The very first line break
  2912. is suppressed (i.e., a line break that follows `\.{\\Y\\B}').
  2913. @<Look ahead for st...@>= {
  2914.   b=a; save_mode=cur_mode; c=0;
  2915.   while (1) {
  2916.     a=get_output();
  2917.     if (a==inserted) continue;
  2918.     if (a==cancel || a==big_cancel) {
  2919.       @<Output saved |indent| or |outdent| tokens@>;
  2920.       goto reswitch; /* |cancel| overrides everything */
  2921.     }
  2922.     if ((a!=' ' && a<indent) || a==backup || a>big_force) {
  2923.       if (save_mode==outer) {
  2924.         if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\B",4)==0)
  2925.           goto reswitch;
  2926.         @<Output saved |indent| or |outdent| tokens@>;
  2927.         out('\\'); out(b-cancel+'0');
  2928. @.\\5@>
  2929. @.\\6@>
  2930. @.\\7@>
  2931.         if (a!=end_translation) finish_line();
  2932.       }
  2933.       else if (a!=end_translation && cur_mode==inner) out(' ');
  2934.       goto reswitch;
  2935.     }
  2936.     if (a==indent) c++;
  2937.     else if (a==outdent) c--;
  2938.     else if (a==opt) a=get_output();
  2939.     else if (a>b) b=a; /* if |a==' '| we have |a<b| */
  2940. @ @<Output saved...@>=
  2941.   for (;c>0;c--) out_str("\\1");
  2942. @.\\1@>
  2943.   for (;c<0;c++) out_str("\\2");
  2944. @.\\2@>
  2945. @ The remaining part of |make_output| is somewhat more complicated. When we
  2946. output a section name, we may need to enter the parsing and translation
  2947. routines, since the name may contain \CEE/ code embedded in
  2948. \pb\ constructions. This \CEE/ code is placed at the end of the active
  2949. input buffer and the translation process uses the end of the active
  2950. |tok_mem| area.
  2951. @<Output a section name@>= {
  2952.   out_str("\\X");
  2953. @.\\X@>
  2954.   cur_xref=(xref_pointer)cur_name->xref;
  2955.   if (cur_xref->num==file_flag) {an_output=1; cur_xref=cur_xref->xlink;}
  2956.   else an_output=0;
  2957.   if (cur_xref->num>=def_flag) {
  2958.     out_section(cur_xref->num-def_flag);
  2959.     if (phase==3) {
  2960.       cur_xref=cur_xref->xlink;
  2961.       while (cur_xref->num>=def_flag) {
  2962.         out_str(", ");
  2963.         out_section(cur_xref->num-def_flag);
  2964.       cur_xref=cur_xref->xlink;
  2965.       }
  2966.     }
  2967.   else out('0'); /* output the section number, or zero if it was undefined */
  2968.   out(':');
  2969.   if (an_output) out_str("\\.{"@q}@>);
  2970. @.\\.@>
  2971.   @<Output the text of the section name@>;
  2972.   if (an_output) out_str(@q{@>" }");
  2973.   out_str("\\X");
  2974. @ @<Output the text...@>=
  2975. sprint_section_name(scratch,cur_name);
  2976. k=scratch;
  2977. k_limit=scratch+strlen(scratch);
  2978. cur_section_name=cur_name;
  2979. while (k<k_limit) {
  2980.   b=*(k++);
  2981.   if (b=='@@') @<Skip next character, give error if not `\.{@@}'@>;
  2982.   if (an_output)
  2983.     switch (b) {
  2984.  case  ' ':case '\\':case '#':case '%':case '$':case '^':
  2985.  case '{': case '}': case '~': case '&': case '_':
  2986.     out('\\'); /* falls through */
  2987. @.\\\ @>
  2988. @.\\\\@>
  2989. @.\\\#@>
  2990. @.\\\%@>
  2991. @.\\\$@>
  2992. @.\\\^@>
  2993. @.\\\{@>@q}@>
  2994. @q{@>@.\\\}@>
  2995. @.\\\~@>
  2996. @.\\\&@>
  2997. @.\\_@>  @q CWEAVE does quote an underscore! @>
  2998.  default: out(b);
  2999.     }
  3000.   else if (b!='|') out(b)
  3001.   else {
  3002.     @<Copy the \CEE/ text into the |buffer| array@>;
  3003.     save_loc=loc; save_limit=limit; loc=limit+2; limit=j+1;
  3004.     *limit='|'; output_C();
  3005.     loc=save_loc; limit=save_limit;
  3006. @ @<Skip next char...@>=
  3007. if (*k++!='@@') {
  3008.   printf("\n! Illegal control code in section name: <");
  3009. @.Illegal control code...@>
  3010.   print_section_name(cur_section_name); printf("> "); mark_error;
  3011. @ The \CEE/ text enclosed in \pb\ should not contain `\.{\v}' characters,
  3012. except within strings. We put a `\.{\v}' at the front of the buffer, so that an
  3013. error message that displays the whole buffer will look a little bit sensible.
  3014. The variable |delim| is zero outside of strings, otherwise it
  3015. equals the delimiter that began the string being copied.
  3016. @<Copy the \CEE/ text into...@>=
  3017. j=limit+1; *j='|'; delim=0;
  3018. while (1) {
  3019.   if (k>=k_limit) {
  3020.     printf("\n! C text in section name didn't end: <");
  3021. @.C text...didn't end@>
  3022.     print_section_name(cur_section_name); printf("> "); mark_error; break;
  3023.   b=*(k++);
  3024.   if (b=='@@') @<Copy a control code into the buffer@>
  3025.   else {
  3026.     if (b=='\'' || b=='"')
  3027.       if (delim==0) delim=b;
  3028.       else if (delim==b) delim=0;
  3029.     if (b!='|' || delim!=0) {
  3030.       if (j>buffer+long_buf_size-3) overflow("buffer");
  3031.       *(++j)=b;
  3032.     }
  3033.     else break;
  3034. @ @<Copy a control code into the buffer@>= {
  3035.   if (j>buffer+long_buf_size-4) overflow("buffer");
  3036.   *(++j)='@@'; *(++j)=*(k++);
  3037. @** Phase two processing.
  3038. We have assembled enough pieces of the puzzle in order to be ready to specify
  3039. the processing in \.{CWEAVE}'s main pass over the source file. Phase two
  3040. is analogous to phase one, except that more work is involved because we must
  3041. actually output the \TEX/ material instead of merely looking at the
  3042. \.{CWEB} specifications.
  3043. @<Predecl...@>=
  3044. void phase_two();
  3045. phase_two() {
  3046. reset_input(); if (show_progress) printf("\nWriting the output file...");
  3047. @.Writing the output file...@>
  3048. section_count=0; format_visible=1; copy_limbo();
  3049. finish_line(); flush_buffer(out_buf,0,0); /* insert a blank line, it looks nice */
  3050. while (!input_has_ended) @<Translate the current section@>;
  3051. @ The output file will contain the control sequence \.{\\Y} between non-null
  3052. sections of a section, e.g., between the \TEX/ and definition parts if both
  3053. are nonempty. This puts a little white space between the parts when they are
  3054. printed. However, we don't want \.{\\Y} to occur between two definitions
  3055. within a single section. The variables |out_line| or |out_ptr| will
  3056. change if a section is non-null, so the following macros `|save_position|'
  3057. and `|emit_space_if_needed|' are able to handle the situation:
  3058. @d save_position save_line=out_line; save_place=out_ptr
  3059. @d emit_space_if_needed if (save_line!=out_line || save_place!=out_ptr)
  3060.   out_str("\\Y");
  3061.   space_checked=1
  3062. @.\\Y@>
  3063. @<Global...@>=
  3064. int save_line; /* former value of |out_line| */
  3065. char *save_place; /* former value of |out_ptr| */
  3066. int sec_depth; /* the integer, if any, following \.{@@*} */
  3067. boolean space_checked; /* have we done |emit_space_if_needed|? */
  3068. boolean format_visible; /* should the next format declaration be output? */
  3069. boolean doing_format=0; /* are we outputting a format declaration? */
  3070. boolean group_found=0; /* has a starred section occurred? */
  3071. @ @<Translate the current section@>= {
  3072.   section_count++;
  3073.   @<Output the code for the beginning of a new section@>;
  3074.   save_position;
  3075.   @<Translate the \TEX/ part of the current section@>;
  3076.   @<Translate the definition part of the current section@>;
  3077.   @<Translate the \CEE/ part of the current section@>;
  3078.   @<Show cross-references to this section@>;
  3079.   @<Output the code for the end of a section@>;
  3080. @ Sections beginning with the \.{CWEB} control sequence `\.{@@\ }' start in the
  3081. output with the \TEX/ control sequence `\.{\\M}', followed by the section
  3082. number. Similarly, `\.{@@*}' sections lead to the control sequence `\.{\\N}'.
  3083. In this case there's an additional parameter, representing one plus the
  3084. specified depth, immediately after the \.{\\N}.
  3085. If the section has changed, we put \.{\\*} just after the section number.
  3086. @<Output the code for the beginning...@>=
  3087. if (*(loc-1)!='*') out_str("\\M");
  3088. @.\\M@>
  3089. else {
  3090.   while (*loc == ' ') loc++;
  3091.   if (*loc=='*') { /* ``top'' level */
  3092.     sec_depth = -1;
  3093.     loc++;
  3094.   else {
  3095.     for (sec_depth=0; xisdigit(*loc);loc++)
  3096.       sec_depth = sec_depth*10 + (*loc) -'0';
  3097.   while (*loc == ' ') loc++; /* remove spaces before group title */
  3098.   group_found=1;
  3099.   out_str("\\N");
  3100. @.\\N@>
  3101.   {@+ char s[32];@+sprintf(s,"{%d}",sec_depth+1);@+out_str(s);@+}
  3102.   if (show_progress)
  3103.   printf("*%d",section_count); update_terminal; /* print a progress report */
  3104. out_str("{");out_section(section_count); out_str("}");
  3105. @ In the \TEX/ part of a section, we simply copy the source text, except that
  3106. index entries are not copied and \CEE/ text within \pb\ is translated.
  3107. @<Translate the \T...@>= do {
  3108.   next_control=copy_TeX();
  3109.   switch (next_control) {
  3110.     case '|': init_stack; output_C(); break;
  3111.     case '@@': out('@@'); break;
  3112.     case TeX_string: case noop:
  3113.     case xref_roman: case xref_wildcard: case xref_typewriter:
  3114.     case section_name: loc-=2; next_control=get_next(); /* skip to \.{@@>} */
  3115.       if (next_control==TeX_string)
  3116.         err_print("! TeX string should be in C text only"); break;
  3117. @.TeX string should be...@>
  3118.     case thin_space: case math_break: case ord:
  3119.     case line_break: case big_line_break: case no_line_break: case join:
  3120.     case pseudo_semi: case macro_arg_open: case macro_arg_close:
  3121.     case output_defs_code:
  3122.         err_print("! You can't do that in TeX text"); break;
  3123. @.You can't do that...@>
  3124. } while (next_control<format_code);
  3125. @ When we get to the following code we have |next_control>=format_code|, and
  3126. the token memory is in its initial empty state.
  3127. @<Translate the d...@>=
  3128. space_checked=0;
  3129. while (next_control<=definition) { /* |format_code| or |definition| */
  3130.   init_stack;
  3131.   if (next_control==definition) @<Start a macro definition@>@;
  3132.   else @<Start a format definition@>;
  3133.   outer_parse(); finish_C(format_visible); format_visible=1;
  3134.   doing_format=0;
  3135. @ The |finish_C| procedure outputs the translation of the current
  3136. scraps, preceded by the control sequence `\.{\\B}' and followed by the
  3137. control sequence `\.{\\par}'. It also restores the token and scrap
  3138. memories to their initial empty state.
  3139. A |force| token is appended to the current scraps before translation
  3140. takes place, so that the translation will normally end with \.{\\6} or
  3141. \.{\\7} (the \TEX/ macros for |force| and |big_force|). This \.{\\6} or
  3142. \.{\\7} is replaced by the concluding \.{\\par} or by \.{\\Y\\par}.
  3143. @<Predecl...@>=
  3144. void finish_C();
  3145. finish_C(visible) /* finishes a definition or a \CEE/ part */
  3146.   boolean visible; /* nonzero if we should produce \TEX/ output */
  3147.   text_pointer p; /* translation of the scraps */
  3148.   if (visible) {
  3149.     out_str("\\B"); app_tok(force); app_scrap(insert,no_math);
  3150.     p=translate();
  3151. @.\\B@>
  3152.     app(tok_flag+(int)(p-tok_start)); make_output(); /* output the list */
  3153.     if (out_ptr>out_buf+1)
  3154.       if (*(out_ptr-1)=='\\')
  3155. @.\\6@>
  3156. @.\\7@>
  3157. @.\\Y@>
  3158.         if (*out_ptr=='6') out_ptr-=2;
  3159.         else if (*out_ptr=='7') *out_ptr='Y';
  3160.     out_str("\\par"); finish_line();
  3161.   if (text_ptr>max_text_ptr) max_text_ptr=text_ptr;
  3162.   if (tok_ptr>max_tok_ptr) max_tok_ptr=tok_ptr;
  3163.   if (scrap_ptr>max_scr_ptr) max_scr_ptr=scrap_ptr;
  3164.   tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info;
  3165.     /* forget the tokens and the scraps */
  3166. @ Keeping in line with the conventions of the \CEE/ preprocessor (and
  3167. otherwise contrary to the rules of \.{CWEB}) we distinguish here
  3168. between the case that `\.(' immediately follows an identifier and the
  3169. case that the two are separated by a space.  In the latter case, and
  3170. if the identifier is not followed by `\.(' at all, the replacement
  3171. text starts immediately after the identifier.  In the former case,
  3172. it starts after we scan the matching `\.)'.
  3173. @<Start a macro...@>= {
  3174.   if (save_line!=out_line || save_place!=out_ptr)  app(backup);
  3175.   if(!space_checked){emit_space_if_needed;save_position;}
  3176.   app_str("\\D"); /* this will produce `\&{define }' */
  3177. @.\\D@>
  3178.   if ((next_control=get_next())!=identifier)
  3179.     err_print("! Improper macro definition");
  3180. @.Improper macro definition@>
  3181.   else {
  3182.     app('$'); app_cur_id(0);
  3183.     if (*loc=='(')
  3184.   reswitch: switch (next_control=get_next()) {
  3185.       case '(': case ',': app(next_control); goto reswitch;
  3186.       case identifier: app_cur_id(0); goto reswitch;
  3187.       case ')': app(next_control); next_control=get_next(); break;
  3188.       default: err_print("! Improper macro definition"); break;
  3189.     }
  3190.     else next_control=get_next();
  3191.     app_str("$ "); app(break_space);
  3192.     app_scrap(dead,no_math); /* scrap won't take part in the parsing */
  3193. @ @<Start a format...@>= {
  3194.   doing_format=1;
  3195.   if(*(loc-1)=='s' || *(loc-1)=='S') format_visible=0;
  3196.   if(!space_checked){emit_space_if_needed;save_position;}
  3197.   app_str("\\F"); /* this will produce `\&{format }' */
  3198. @.\\F@>
  3199.   next_control=get_next();
  3200.   if (next_control==identifier) {
  3201.     app(id_flag+(int)(id_lookup(id_first, id_loc,normal)-name_dir));
  3202.     app(' ');
  3203.     app(break_space); /* this is syntactically separate from what follows */
  3204.     next_control=get_next();
  3205.     if (next_control==identifier) {
  3206.       app(id_flag+(int)(id_lookup(id_first, id_loc,normal)-name_dir));
  3207.       app_scrap(exp,maybe_math); app_scrap(semi,maybe_math);
  3208.       next_control=get_next();
  3209.     }
  3210.   if (scrap_ptr!=scrap_info+2) err_print("! Improper format definition");
  3211. @.Improper format definition@>
  3212. @ Finally, when the \TEX/ and definition parts have been treated, we have
  3213. |next_control>=begin_C|. We will make the global variable |this_section|
  3214. point to the current section name, if it has a name.
  3215. @<Global...@>=
  3216. name_pointer this_section; /* the current section name, or zero */
  3217. @ @<Translate the \CEE/...@>=
  3218. this_section=name_dir;
  3219. if (next_control<=section_name) {
  3220.   emit_space_if_needed; init_stack;
  3221.   if (next_control==begin_C) next_control=get_next();
  3222.   else {
  3223.     this_section=cur_section;
  3224.     @<Check that '=' or '==' follows this section name, and
  3225.       emit the scraps to start the section definition@>;
  3226.   while  (next_control<=section_name) {
  3227.     outer_parse();
  3228.     @<Emit the scrap for a section name if present@>;
  3229.   finish_C(1);
  3230. @ The title of the section and an $\E$ or $\mathrel+\E$ are made
  3231. into a scrap that should not take part in the parsing.
  3232. @<Check that '='...@>=
  3233. do next_control=get_next();
  3234.   while (next_control=='+'); /* allow optional `\.{+=}' */
  3235. if (next_control!='=' && next_control!=eq_eq)
  3236.   err_print("! You need an = sign after the section name");
  3237. @.You need an = sign...@>
  3238.   else next_control=get_next();
  3239. if (out_ptr>out_buf+1 && *out_ptr=='Y' && *(out_ptr-1)=='\\') app(backup);
  3240.     /* the section name will be flush left */
  3241. @.\\Y@>
  3242. app(section_flag+(int)(this_section-name_dir));
  3243. cur_xref=(xref_pointer)this_section->xref;
  3244. if(cur_xref->num==file_flag) cur_xref=cur_xref->xlink;
  3245. app_str("${}");
  3246. if (cur_xref->num!=section_count+def_flag) {
  3247.   app_str("\\mathrel+"); /*section name is multiply defined*/
  3248.   this_section=name_dir; /*so we won't give cross-reference info here*/
  3249. app_str("\\E"); /* output an equivalence sign */
  3250. @.\\E@>
  3251. app_str("{}$");
  3252. app(force); app_scrap(dead,no_math);
  3253.         /* this forces a line break unless `\.{@@+}' follows */
  3254. @ @<Emit the scrap...@>=
  3255. if (next_control<section_name) {
  3256.   err_print("! You can't do that in C text");
  3257. @.You can't do that...@>
  3258.   next_control=get_next();
  3259. else if (next_control==section_name) {
  3260.   app(section_flag+(int)(cur_section-name_dir));
  3261.   app_scrap(section_scrap,maybe_math);
  3262.   next_control=get_next();
  3263. @ Cross references relating to a named section are given
  3264. after the section ends.
  3265. @<Show cross...@>=
  3266. if (this_section>name_dir) {
  3267.   cur_xref=(xref_pointer)this_section->xref;
  3268.   if (cur_xref->num==file_flag){an_output=1;cur_xref=cur_xref->xlink;}
  3269.   else an_output=0;
  3270.   if (cur_xref->num>def_flag)
  3271.     cur_xref=cur_xref->xlink; /* bypass current section number */
  3272.   footnote(def_flag); footnote(cite_flag); footnote(0);
  3273. @ The |footnote| procedure gives cross-reference information about
  3274. multiply defined section names (if the |flag| parameter is
  3275. |def_flag|), or about references to a section name
  3276. (if |flag==cite_flag|), or to its uses (if |flag==0|). It assumes that
  3277. |cur_xref| points to the first cross-reference entry of interest, and it
  3278. leaves |cur_xref| pointing to the first element not printed.  Typical outputs:
  3279. `\.{\\A101.}'; `\.{\\Us 370\\ET1009.}';
  3280. `\.{\\As 8, 27\\*\\ETs64.}'.
  3281. Note that the output of \.{CWEAVE} is not English-specific; users may
  3282. supply new definitions for the macros \.{\\A}, \.{\\As}, etc.
  3283. @<Predecl...@>=
  3284. void footnote();
  3285. footnote(flag) /* outputs section cross-references */
  3286. sixteen_bits flag;
  3287.   xref_pointer q; /* cross-reference pointer variable */
  3288.   if (cur_xref->num<=flag) return;
  3289.   finish_line(); out('\\');
  3290. @.\\A@>
  3291. @.\\Q@>
  3292. @.\\U@>
  3293.   out(flag==0? 'U': flag==cite_flag? 'Q': 'A');
  3294.   @<Output all the section numbers on the reference list |cur_xref|@>;
  3295.   out('.');
  3296. @ The following code distinguishes three cases, according as the number
  3297. of cross-references is one, two, or more than two. Variable |q| points
  3298. to the first cross-reference, and the last link is a zero.
  3299. @<Output all the section numbers...@>=
  3300. q=cur_xref; if (q->xlink->num>flag) out('s'); /* plural */
  3301. while (1) {
  3302.   out_section(cur_xref->num-flag);
  3303.   cur_xref=cur_xref->xlink; /* point to the next cross-reference to output */
  3304.   if (cur_xref->num<=flag) break;
  3305.   if (cur_xref->xlink->num>flag) out_str(", "); /* not the last */
  3306.   else {out_str("\\ET"); /* the last */
  3307. @.\\ET@>
  3308.   if (cur_xref != q->xlink) out('s'); /* the last of more than two */
  3309. @ @<Output the code for the end of a section@>=
  3310. out_str("\\fi"); finish_line();
  3311. @.\\fi@>
  3312. flush_buffer(out_buf,0,0); /* insert a blank line, it looks nice */
  3313. @** Phase three processing.
  3314. We are nearly finished! \.{CWEAVE}'s only remaining task is to write out the
  3315. index, after sorting the identifiers and index entries.
  3316. If the user has set the |no_xref| flag (the |-x| option on the command line),
  3317. just finish off the page, omitting the index, section name list, and table of
  3318. contents.
  3319. @<Predecl...@>=
  3320. void phase_three();
  3321. phase_three() {
  3322. if (no_xref) {
  3323.   finish_line();
  3324.   out_str("\\end");
  3325. @.\\end@>
  3326.   finish_line();
  3327. else {
  3328.   phase=3; if (show_progress) printf("\nWriting the index...");
  3329. @.Writing the index...@>
  3330.   finish_line();
  3331.   if ((idx_file=fopen(idx_file_name,"w"))==NULL)
  3332.     fatal("! Cannot open index file ",idx_file_name);
  3333. @.Cannot open index file@>
  3334.   if (change_exists) {
  3335.     @<Tell about changed sections@>; finish_line(); finish_line();
  3336.   out_str("\\inx"); finish_line();
  3337. @.\\inx@>
  3338.   active_file=idx_file; /* change active file to the index file */
  3339.   @<Do the first pass of sorting@>;
  3340.   @<Sort and output the index@>;
  3341.   finish_line(); fclose(active_file); /* finished with |idx_file| */
  3342.   active_file=tex_file; /* switch back to |tex_file| for a tic */
  3343.   out_str("\\fin"); finish_line();
  3344. @.\\fin@>
  3345.   if ((scn_file=fopen(scn_file_name,"w"))==NULL)
  3346.     fatal("! Cannot open section file ",scn_file_name);
  3347. @.Cannot open section file@>
  3348.   active_file=scn_file; /* change active file to section listing file */
  3349.   @<Output all the section names@>;
  3350.   finish_line(); fclose(active_file); /* finished with |scn_file| */
  3351.   active_file=tex_file;
  3352.   if (group_found) out_str("\\con");@+else out_str("\\end");
  3353. @.\\con@>
  3354. @.\\end@>
  3355.   finish_line();
  3356.   fclose(active_file);
  3357. if (show_happiness) printf("\nDone.");
  3358. check_complete(); /* was all of the change file used? */
  3359. @ Just before the index comes a list of all the changed sections, including
  3360. the index section itself.
  3361. @<Global...@>=
  3362. sixteen_bits k_section; /* runs through the sections */
  3363. @ @<Tell about changed sections@>= {
  3364.   /* remember that the index is already marked as changed */
  3365.   k_section=0;
  3366.   while (!changed_section[++k_section]);
  3367.   out_str("\\ch ");
  3368. @.\\ch@>
  3369.   out_section(k_section);
  3370.   while (k_section<section_count) {
  3371.     while (!changed_section[++k_section]);
  3372.     out_str(", "); out_section(k_section);
  3373.   out('.');
  3374. @ A left-to-right radix sorting method is used, since this makes it easy to
  3375. adjust the collating sequence and since the running time will be at worst
  3376. proportional to the total length of all entries in the index. We put the
  3377. identifiers into 102 different lists based on their first characters.
  3378. (Uppercase letters are put into the same list as the corresponding lowercase
  3379. letters, since we want to have `$t<\\{TeX}<\&{to}$'.) The
  3380. list for character |c| begins at location |bucket[c]| and continues through
  3381. the |blink| array.
  3382. @<Global...@>=
  3383. name_pointer bucket[256];
  3384. name_pointer next_name; /* successor of |cur_name| when sorting */
  3385. name_pointer blink[max_names]; /* links in the buckets */
  3386. @ To begin the sorting, we go through all the hash lists and put each entry
  3387. having a nonempty cross-reference list into the proper bucket.
  3388. @<Do the first pass...@>= {
  3389. int c;
  3390. for (c=0; c<=255; c++) bucket[c]=NULL;
  3391. for (h=hash; h<=hash_end; h++) {
  3392.   next_name=*h;
  3393.   while (next_name) {
  3394.     cur_name=next_name; next_name=cur_name->link;
  3395.     if (cur_name->xref!=(char*)xmem) {
  3396.       c=(eight_bits)((cur_name->byte_start)[0]);
  3397.       if (xisupper(c)) c=tolower(c);
  3398.       blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
  3399.     }
  3400. @ During the sorting phase we shall use the |cat| and |trans| arrays from
  3401. \.{CWEAVE}'s parsing algorithm and rename them |depth| and |head|. They now
  3402. represent a stack of identifier lists for all the index entries that have
  3403. not yet been output. The variable |sort_ptr| tells how many such lists are
  3404. present; the lists are output in reverse order (first |sort_ptr|, then
  3405. |sort_ptr-1|, etc.). The |j|th list starts at |head[j]|, and if the first
  3406. |k| characters of all entries on this list are known to be equal we have
  3407. |depth[j]==k|.
  3408. @ @<Rest of |trans_plus| union@>=
  3409. name_pointer Head;
  3410. @ @d depth cat /* reclaims memory that is no longer needed for parsing */
  3411. @d head trans_plus.Head /* ditto */
  3412. @f sort_pointer int
  3413. @d sort_pointer scrap_pointer /* ditto */
  3414. @d sort_ptr scrap_ptr /* ditto */
  3415. @d max_sorts max_scraps /* ditto */
  3416. @<Global...@>=
  3417. eight_bits cur_depth; /* depth of current buckets */
  3418. char *cur_byte; /* index into |byte_mem| */
  3419. sixteen_bits cur_val; /* current cross-reference number */
  3420. sort_pointer max_sort_ptr; /* largest value of |sort_ptr| */
  3421. @ @<Set init...@>=
  3422. max_sort_ptr=scrap_info;
  3423. @ The desired alphabetic order is specified by the |collate| array; namely,
  3424. |collate[0]<collate[1]<@t$\cdots$@><collate[100]|.
  3425. @<Global...@>=
  3426. eight_bits collate[102+128]; /* collation order */
  3427. @^high-bit character handling@>
  3428. @ We use the order $\hbox{null}<\.\ <\hbox{other characters}<{}$\.\_${}<
  3429. \.A=\.a<\cdots<\.Z=\.z<\.0<\cdots<\.9.$ Warning: The collation mapping
  3430. needs to be changed if ASCII code is not being used.
  3431. @^ASCII code dependencies@>
  3432. @^high-bit character handling@>
  3433. @<Set init...@>=
  3434. collate[0]=0; strcpy(collate+1," \1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\
  3435. \20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\
  3436. !\42#$%&'()*+,-./:;<=>?@@[\\]^`{|}~_\
  3437. abcdefghijklmnopqrstuvwxyz0123456789\
  3438. \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\
  3439. \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\
  3440. \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\
  3441. \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\
  3442. \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\
  3443. \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\
  3444. \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\
  3445. \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\
  3446. @ Procedure |unbucket| goes through the buckets and adds nonempty lists
  3447. to the stack, using the collating sequence specified in the |collate| array.
  3448. The parameter to |unbucket| tells the current depth in the buckets.
  3449. Any two sequences that agree in their first 255 character positions are
  3450. regarded as identical.
  3451. @d infinity 255 /* $\infty$ (approximately) */
  3452. @<Predecl...@>=
  3453. void  unbucket();
  3454. unbucket(d) /* empties buckets having depth |d| */
  3455. eight_bits d;
  3456.   int c;  /* index into |bucket|; cannot be a simple |char| because of sign
  3457.     comparison below*/
  3458.   for (c=100+128; c>= 0; c--) if (bucket[collate[c]]) {
  3459. @^high-bit character handling@>
  3460.     if (sort_ptr>=scrap_info_end) overflow("sorting");
  3461.     sort_ptr++;
  3462.     if (sort_ptr>max_sort_ptr) max_sort_ptr=sort_ptr;
  3463.     if (c==0) sort_ptr->depth=infinity;
  3464.     else sort_ptr->depth=d;
  3465.     sort_ptr->head=bucket[collate[c]]; bucket[collate[c]]=NULL;
  3466. @ @<Sort and output...@>=
  3467. sort_ptr=scrap_info; unbucket(1);
  3468. while (sort_ptr>scrap_info) {
  3469.   cur_depth=sort_ptr->depth;
  3470.   if (blink[sort_ptr->head-name_dir]==0 || cur_depth==infinity)
  3471.     @<Output index entries for the list at |sort_ptr|@>@;
  3472.   else @<Split the list at |sort_ptr| into further lists@>;
  3473. @ @<Split the list...@>= {
  3474.   eight_bits c;
  3475.   next_name=sort_ptr->head;
  3476.   do {
  3477.     cur_name=next_name; next_name=blink[cur_name-name_dir];
  3478.     cur_byte=cur_name->byte_start+cur_depth;
  3479.     if (cur_byte==(cur_name+1)->byte_start) c=0; /* hit end of the name */
  3480.     else {
  3481.       c=(eight_bits) *cur_byte;
  3482.       if (xisupper(c)) c=tolower(c);
  3483.     }
  3484.   blink[cur_name-name_dir]=bucket[c]; bucket[c]=cur_name;
  3485.   } while (next_name);
  3486.   --sort_ptr; unbucket(cur_depth+1);
  3487. @ @<Output index...@>= {
  3488.   cur_name=sort_ptr->head;
  3489.   do {
  3490.     out_str("\\I");
  3491. @.\\I@>
  3492.     @<Output the name at |cur_name|@>;
  3493.     @<Output the cross-references at |cur_name|@>;
  3494.     cur_name=blink[cur_name-name_dir];
  3495.   } while (cur_name);
  3496.   --sort_ptr;
  3497. @ @<Output the name...@>=
  3498. switch (cur_name->ilk) {
  3499.   case normal: if (is_tiny(cur_name)) out_str("\\|");
  3500.     else {char *j;
  3501.       for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
  3502.         if (xislower(*j)) goto lowcase;
  3503.       out_str("\\."); break;
  3504. lowcase: out_str("\\\\");
  3505.     }
  3506.   break;
  3507. @.\\|@>
  3508. @.\\.@>
  3509. @.\\\\@>
  3510.   case roman: break;
  3511.   case wildcard: out_str("\\9"); break;
  3512. @.\\9@>
  3513.   case typewriter: out_str("\\."); break;
  3514. @.\\.@>
  3515.   case custom: case quoted: {char *j; out_str("$\\");
  3516.     for (j=cur_name->byte_start;j<(cur_name+1)->byte_start;j++)
  3517.       out(isxalpha(*j)? 'x' : *j);
  3518.     out('$');
  3519.     goto name_done;
  3520.     }
  3521.   default: out_str("\\&");
  3522. @.\\\&@>
  3523. out_name(cur_name);
  3524. name_done:
  3525. @ Section numbers that are to be underlined are enclosed in
  3526. `\.{\\[}$\,\ldots\,$\.]'.
  3527. @<Output the cross-references...@>=
  3528. @<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>;
  3529.   out_str(", "); cur_val=cur_xref->num;
  3530.   if (cur_val<def_flag) out_section(cur_val);
  3531.   else {out_str("\\["); out_section(cur_val-def_flag); out(']');}
  3532. @.\\[@>
  3533.   cur_xref=cur_xref->xlink;
  3534. } while (cur_xref!=xmem);
  3535. out('.'); finish_line();
  3536. @ List inversion is best thought of as popping elements off one stack and
  3537. pushing them onto another. In this case |cur_xref| will be the head of
  3538. the stack that we push things onto.
  3539. @<Global...@>=
  3540. xref_pointer next_xref, this_xref;
  3541.   /* pointer variables for rearranging a list */
  3542. @ @<Invert the cross-reference list at |cur_name|, making |cur_xref| the head@>=
  3543. this_xref=(xref_pointer)cur_name->xref; cur_xref=xmem;
  3544.   next_xref=this_xref->xlink; this_xref->xlink=cur_xref;
  3545.   cur_xref=this_xref; this_xref=next_xref;
  3546. } while (this_xref!=xmem);
  3547. @ The following recursive procedure walks through the tree of section names and
  3548. prints them.
  3549. @^recursion@>
  3550. @<Predecl...@>=
  3551. void section_print();
  3552. section_print(p) /* print all section names in subtree |p| */
  3553. name_pointer p;
  3554.   if (p) {
  3555.     section_print(p->llink); out_str("\\I");
  3556. @.\\I@>
  3557.     tok_ptr=tok_mem+1; text_ptr=tok_start+1; scrap_ptr=scrap_info; init_stack;
  3558.     app(p-name_dir+section_flag); make_output();
  3559.     footnote(cite_flag);
  3560.     footnote(0); /* |cur_xref| was set by |make_output| */
  3561.     finish_line();@/
  3562.     section_print(p->rlink);
  3563. @ @<Output all the section names@>=section_print(root)
  3564. @ Because on some systems the difference between two pointers is a |long|
  3565. rather than an |int|, we use \.{\%ld} to print these quantities.
  3566. print_stats() {
  3567.   printf("\nMemory usage statistics:\n");
  3568. @.Memory usage statistics:@>
  3569.   printf("%ld names (out of %ld)\n",
  3570.             (long)(name_ptr-name_dir),(long)max_names);
  3571.   printf("%ld cross-references (out of %ld)\n",
  3572.             (long)(xref_ptr-xmem),(long)max_refs);
  3573.   printf("%ld bytes (out of %ld)\n",
  3574.             (long)(byte_ptr-byte_mem),(long)max_bytes);
  3575.   printf("Parsing:\n");
  3576.   printf("%ld scraps (out of %ld)\n",
  3577.             (long)(max_scr_ptr-scrap_info),(long)max_scraps);
  3578.   printf("%ld texts (out of %ld)\n",
  3579.             (long)(max_text_ptr-tok_start),(long)max_texts);
  3580.   printf("%ld tokens (out of %ld)\n",
  3581.             (long)(max_tok_ptr-tok_mem),(long)max_toks);
  3582.   printf("%ld levels (out of %ld)\n",
  3583.             (long)(max_stack_ptr-stack),(long)stack_size);
  3584.   printf("Sorting:\n");
  3585.   printf("%ld levels (out of %ld)\n",
  3586.             (long)(max_sort_ptr-scrap_info),(long)max_scraps);
  3587. @** Index.
  3588. If you have read and understood the code for Phase III above, you know what
  3589. is in this index and how it got here. All sections in which an identifier is
  3590. used are listed with that identifier, except that reserved words are
  3591. indexed only when they appear in format definitions, and the appearances
  3592. of identifiers in section names are not indexed. Underlined entries
  3593. correspond to where the identifier was declared. Error messages, control
  3594. sequences put into the output, and a few
  3595. other things like ``recursion'' are indexed here too.
  3596.